Sie sind auf Seite 1von 52

Apostila De C++ / BCB

Ricardo Pupo Larguesa Cefet SP (Uned Cubato)

- Introduo:
Esta primeira aula serve para introduzir a ferramenta adotada para este semestre: O Borland C++ builder. Ser feita uma reviso com o objetivo de amadurecer certos conceitos que so fundamentais no desenvolvimento da matria, principalmente de programao orientada a objeto. O C++ Builder pode ser considerada como uma das mais completas ferramentas, no s porque a Borland est desenvolvendo plataformas para outros sistemas operacionais (Kylix) mas tambm por causa da compatibilidade entre o C++ Builder e o Delphi. possvel utilizar aplicaes em conjunto e migrar facilmente de uma linguegam para outra, utilizar funes e formulrios mistos, entre outras facilidades. Dessa forma, sabendo que a turma j possui slidos conceitos de Delphi e de C++, pode-se tirar um proveito ainda maior dessa poderosa ferramenta da Borland.

- A linguagem C/C++:
A linguagem C foi criada na dcada de 70, por Dennis Ritchie, nos laboratrios Bell. Para tanto , ele utilizou o sistema operacional Unix e a linguagem BCPL. Baseado nessa linguagem, Ken Thompson, que tambm trabalhou na criao de C criou a linguagem B. Como a linguagem de Richie foi posterior, recebeu o nome de C. Dessa forma podemos concluir que esses gnios no tinham muita criatividade para bolar nomes para suas aplicaes e podemos ainda alimentar nossa sede de cultura intil. Na verdade, a linguagem C chega a ser considerada uma "linguagem de nvel mdio" e , na verdade, uma linguagem estruturada. Digo que ela pode ser considerada uma linguagem de nvel mdio porque a linguagem em si mais complexa e pouco malevel e sua representao gramtica no l muito intuitiva. Porm, se fosse muito fcil no precisaramos de cursos e, alm disso, qualquer pessoa poderia utiliz-la e perderamos nossos empregos. Portanto no adianta reclamar!!!! O C++ simplesmente a verso de C orientada a objetos. O que pode parecer uma linguagem nova no passa de novo conceito de programao e uma forma nova de tratar variveis. claro que o efeito provocado por essas "pequenas" diferenas grande mas ns no podemos deixar isso nos abater. Alm do mais, como veremos adiante, essa nova metodologia facilita nossa vida a bea e muito mais fcil de entender e de organizar. O conceito de linguagem orientada a objeto antigo, assim como o C++, porm hoje, com aplicaes visuais e o estardalhao da multimdia, precisamos sempre de ferramentas que nos privem de processos repetitivos e cansativos e nada melhor para lidar com isso do que uma linguagem visual orientada a objeto. Vocs j puderam ver isso com o Delphi. A facilidade para se fazer um programa aparentemente complexo absurda tendo em vista todo o conhecimento que tnhamos de programao. E qualquer um sabe que um programa simples porm bonitinho vale para um leigo muito mais do que um programa complexo, otimizado, rpido, excelente e feio. Como ns, seres humanos, somos egostas, desalmados e interesseiros estamos interessados mesmo no dinheiro!! Brincadeiras a parte, devemos dominar essas ferramentas mesmo assim!!! No significa tambm que tenhamos que fazer programas ruins e bonitinhos para vendermos caro. Significa que podemos continuar fazendo nossas aplicaes com a mesma qualidade oferecendo ao cliente as facilidade das interaes visuais e da multimdia.

- Exemplo de Projeto de Software:


Antes de entrar na linguagem orientada a objetos, acho interessante mostrar o que pode at parecer uma piada mas a pura representao da realidade (claro que atravs de uma metfora).

Com esse exemplo, podemos perceber a importncia de um planejamento bem elaborado e organizado. A linguagem orientada a objetos facilita nossa vida nesse sentido. Agora chega de papo furado e vamos ao que interessa.

- Tipos de variveis do C++:

As variveis so o aspecto fundamental das linguagens de computao. No C++, assim como na maioria das outras linguagens, a varivel um espao na memria reservado para armazenar um tipo especfico de dado e esse espao na memria referenciado por um nome. Isso significa que o valor contido nesse espao de memria pode mudar com o passar do tempo. Utiliza-se uma palavra reservada para fazer a declarao da varivel determinando o tipo dela e posicionando seu lugar na memria. Por exemplo: #include <iostream.h> void main() { int numero; } Nesse exemplo, a palavra reservada int determina que a varivel ser do tipo inteira e numero o nome dado como referncia para acessar o espao de memria reservado dessa varivel. O C bem chatinho em relao aos nomes de variveis. Pode-se utilizar quantos caracteres quiser com o primeiro sendo obrigatoriamente uma letra ou caractere de sublinhado podendo ainda utilizar nmeros de 0 a 9 nos outros caracteres. Alm disso, o C case sensitive. A varivel 'Casa diferente de 'casa'. Os tipos de variveis bsicas do C++ so 5 e so as seguintes:

TIPO char int float double void

BIT 8 16 32 64 0

BYTES 1 2 4 8 0

ESCALA -128 a 127 -32768 a 32767 3.4E-38 a 3.4E+38 1.7E-308 a 1.7E+308 nenhum valor

Com exceo de void, que serve para indicar que uma funo no tem valor de retorno, os tipos de dados bsicos pelos modificadores long, short e unsigned. Se o modificador for utilizado sem que seja especificado o tipo bsico o compilador assume o tipo int. Os modificadores e suas utilizaes so mostradas a seguir:

TIPO unsigned char unsigned short long unsigned long long double

BIT 8 16 16 32 32 80

BYTES 1 2 2 4 4 10

ESCALA 0 a 255 0 a 65535 -32768 a 32767 -2147483648 a 2147483647 0 a 4294967295 3.4E-4932 a 1.1E+4932

- Constantes:
Uma constante, como o nome j diz, possui um valor fixo e inaltervel. uma "varivel invarivel" (que piada sem graa!!!) e serve basicamente para organizar o cdigo e facilitar a compreenso do mesmo. Os nmeros constantes podem ser escritos nas seguintes bases numricas: DECIMAL: Sem segredo, da forma como estamos acostumados. Ex: 10, 33, 69, 12237514. HEXADECIMAL: Escritos na base 16, precedidos de 0x. Ex: 0xbabaca, 0xaf8, 0x12e. OCTAL: Escritos na base 8, precedidos de 0. Ex: 05150, 0171. CARACTERE: Escritos entre aspas simples. Ex: 'a', 'e', 'i'. CADEIA DE CARACTERES: Escritos entre aspas duplas. Ex: "exemplo", "programa".

- A Diretiva #define:
A diretiva #define usada para definir constantes simblicas com nomes apropriados. O nome que segue a diretiva chamado identificador e a frase aps o identificador chamada texto. Por conveno o identificador escrito sempre com letras maisculas e cada diretiva deve ser escrita em uma linha nova. Por exemplo: #include <iostream.h> #define GRAVIDADE 9,8 void main() { int peso, massa; cin >> massa; peso = massa * GRAVIDADE; } Nesse caso o compilador substituir a expresso gravidade por 9,8 e substituiria qualquer ocorrncia da expresso GRAVIDADE. Dessa forma, evitaria a utilizao de um espao de memria reservado para uma constante. Porem a constante tem a vantagem de ser acusada pelo compilador se for usada ou declarada de maneira errada. Isso no acontece coma diretiva #define. Porm, a diretiva #define pode ser utilizada para substituir frases inteiras, independentemente de tipo.

- Operadores aritmticos:
O C++ oferece cinco operadores binrios e um operador aritmtico unrio. So eles:

Unrio: - Menos unrio. Binrio: + Soma - Subtrao * Multiplicao / Diviso % Mdulo Os operadores +, -, * e / representam soma, subtrao, multiplicao e diviso, respectivamente, como dito acima. O operador mdulo opera somente com operandos inteiros e retorna o resto da diviso. O Operador unrio - altera o sinal do operando.

- Operadores de incremento (++) e de decremento(--)


So operadores unrios que adicionam e subtraem 1 varivel operando. Eles podem ser prefixado (colocados antes da varivel) e ps-fixado (colocados aps a varivel). Ex: x = x + 1; equivale a ++x ou x++ O mesmo acontece com o operador --. A diferena entre os operadores prefixado e psfixado que o prefixado executa a ao antes de executar a instruo enquanto que o psfixado executa sua ao logo aps a instruo ter sido realizada.

- Operadores de atribuio e operadores relacionais:


Alm do operador de atribuio simples =, existem mais 5 operadores binrios que, alm da atribuio, executam alguma ao aritmtica. So eles: +=, -=, *=, /= e %=. O primeiro operador representa a ao aritmtica que ser executada e o operando que precede o operador ter o resultado atribu-lo para si.

Os operadores relacionais so os seguintes:

> >= < <= == !=

maior maior ou igual menor menor ou igual igual diferente Esses operadores so utilizados em laos e comandos de deciso.

- Operadores lgicos:
So os comparadores lgicos: &&, || e ! que representam E, OU e NO respectivamente.

- Tabela de Precedncia:
OPERADOR + -! * / % + < <= > >= == != && || ?: = *= /= %= TIPOS menos unrio incremento prefixado ou ps-fixado decremento prefixado ou ps-fixado lgico no multiplicao aritmtica diviso aritmtica mdulo aritmtico mais aritmtico menos aritmtico menor relacional menor ou igual relacional maior relacional maior ou igual relacional igual relacional diferente relacional E lgico OU lgico Condicional Atribuio Aritmtico de atribuio (vezes) Aritmtico de atribuio (divide) Aritmtico de atribuio (mdulo)

+= -=

Aritmtico de atribuio (soma) Aritmtico de atribuio (menos)

Laos de repetio
Laos de repetio so, como o prprio nome j diz, comandos utilizados para repetir uma instruo ou mais durante uma condio especfica. Esse comandos podem se encaixar em trs estruturas que so: for while do-while

O lao for
Sua utilizao a mais especfica de todas. Seus parmetros pedem todas as informaes para uma rotina completa. Para exemplificar escreveremos em um componente ListBox a tabuada do 5: void __fastcall TForm1::Button1Click(TObject *Sender) { ListBox1->Clear(); for (int i = 0; i < 11; i++) { ListBox1->Items->Add("5 x " + IntToStr(i) + " = " + IntToStr(5 * i)); } } O ListBox mostrar o valor de (5 * i) 11 vezes, de 0 at 10. A sintaxe do comando simples. necessrio passar, atravs dos parnteses, trs argumentos separados por ponto e vrgula. O primeiro a inicializao da varivel e, se necessrio, sua criao. O segundo a condio do lao. O terceiro o incremento da varivel. No precisa ser necessariamente incremento de 1 em 1. Pode ser qualquer instruo aritmtica. Por ex: (i--, i+2, i*3/4 +i, etc...) for (int i = 0; i < 11; i++) { }

O lao while
Sua utilizao a mais til em situaes onde o lao pode terminar inesperadamente, dependendo das circunstncias dos processos. Sua sintaxe ainda mais fcil que o for. Basta colocar a condio entre parnteses como segue abaixo:

void __fastcall TForm1::Button1Click(TObject *Sender) { int i = 0; ListBox1->Clear(); while (i < 11) { ListBox1->Items->Add("5 x " + IntToStr(i) + " = " + IntToStr(5 * i)); i++; } } O ListBox mostrar o valor de (5 * i) 11 vezes, de 0 at 10 da mesma forma que com o for.

O lao do-while
Caso seja necessrio fazer a verificao na condio no final da rotina, utiliza-se o lao dowhile:

void __fastcall TForm1::Button1Click(TObject *Sender) { int i = -1; ListBox1->Clear(); do { i++; ListBox1->Items->Add("5 x " + IntToStr(i) + " = " + IntToStr(5 * i)); } while (i < 10); } O ListBox mostrar o valor de (5 * i) 11 vezes, de 0 at 10 da mesma forma que com o for e que o while isolado. A diferena que, nesse caso, precisamos inicializar a varivel i com o valor -1 porque a primeira instruo da rotina o incremento.

Lao aninhados
Pode-se usar dentro de um lao quantos laos forem necessrios. Um lao dentro de outro lao recebe o nome de lao aninhado.

Marizes ou arrays
Matriz nada mais do que um tipo de dado que seqenciado na memria quantas vezes forem necessrias, uma coleo de variveis. Isto significa que, se voc precisar registrar o valor dos salrios de 20 funcionrios por exemplo, voc pode criar uma cadeia de variveis

tambm chamada matriz ou arrays. Dessa forma, voc garante que as variveis sejam alocada uma aps a outra na memria facilitando sua utilizao. Alm disso, voc pode utiliz-la em laos de repetio (veremos logo a seguir). Por exemplo: int Salarios[20]; Nesse exemplo foram criadas 20 variveis que voc acessa atribuindo dentro dos colchetes o valor da varivel. Por exemplo: Salarios[0] = 1200; Salarios[9] = 1150; Deve-se tomar cuidado porque as variveis criadas ficam alocadas na matriz a partir de 0, ou seja, neste exemplo esto de 0 at 19. Podemos ainda substituir o nmero que atribui a quantidade de variveis por uma constante ou varivel a fim de alterar durante a compilao o nmero de variveis criadas. A forma de atribuir valores s matrizes em sua declarao colocar os valores entre chaves, separados por vrgula. Exemplo: int Salarios[5] = {1000, 1150, 1200, 800, 170, 2100}; Como j podemos imaginar, os elementos das matrizes podem ser de qualquer tipo (int, char, AnsiString, float, etc). Inclusive do tipo matriz. Mas que diabos isso significa? Significa que uma matriz pode ter mais de uma dimenso. Por exemplo: int ex2D[3] [3]; //Exemplo de matriz de duas dimenses. int ex3D[3] [3] [3] //Exemplo de matriz de trs dimenses. Para exemplificar, experimente fazer esse algortmo e entender como as matrizes so fceis de se entender e trabalhar: //---------------------------------------------------------------------#include <vcl.h> #pragma hdrstop #include "Unit1.h" //---------------------------------------------------------------------#pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; //---------------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { }

//---------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender) { int Ex1[3] = {0, 1, 2 }; int Ex2[3][3] = { {0, 1, 2 }, {3, 4, 5 }, {6, 7, 8 } }; int Ex3[3][3][3] = { { {0, 1, 2 }, {3, 4, 5 }, {6, 7, 8 } }, { {9, 10,11}, {12,13,14}, {15,16,17} }, { {18,19,20}, {21,22,23}, {24,25,26} } }; for (int i=0; i<3; i++) for (int j=0; j<3; j++) for (int k=0; k<3; k++) ListBox1->Items->Add(IntToStr(i) + IntToStr(j) + IntToStr(k) + " ->" + IntToStr(Ex1[i]) + " - " + IntToStr(Ex2[i][j]) + " - " + IntToStr(Ex3[i][j][k])); } //----------------------------------------------------------------------

- Ponteiros
Um ponteiro uma varivel que guarda um endereo de memria. Indica onde uma varivel est localizada e no o que est armazenado. Eles so normalmente utilizados para manipular elementos de matrizes, receber argumentos em funes que necessitem modificar o argumento original, passar strings de uma funo para outra, us-los no lugar de matrizes, criar estruturas de dados complexas e (Ufa!!) alocar e desalocar memria do sistema. Em C++ existem os ponteiros variveis, que um tipo especial concebido para conter o endereo de uma outra varivel. No exemplo que segue, podemos ver a utilizao de outro operador unrio: O operador de endereos '&'. Este operador se utiliza de seu operando para mostrar ao usurio o endereo solicitado. void __fastcall TForm1::Button1Click(TObject *Sender) { int i = 10, j = 20, k = 30; ShowMessage(IntToHex((int)&i, 6)); ShowMessage(IntToHex((int)&j, 6)); ShowMessage(IntToHex((int)&k, 6)); } As mensagens exibidas sero;

12F38C <-- Endereo de i

12F388 <-- Endereo de j 12F384 <-- Endereo de k

No se pode confundir este operador com o operador de referncia que pode ser utilizado. O operador de referncia o mesmo smbolo, porm colocado aps a varivel e serve para passar variveis por referncia. Por exemplo: Pode-se passar argumentos para uma funo de trs maneiras: Por valor, por referncia e por ponteiro. Da primeira forma, os valores so passados, a funo copia os valores dos argumentos para outras variveis e executa as aes. Se o voc quiser alterar os valores das variveis passadas como argumentos durante o processo, no funciona. Ento, h a necessidade de passar os argumentos por referncia ou por ponteiro. E o que essa desgraa faz exatamente? Vamos tomar como exemplo a seguinte situao: Uma funo que faa um reajuste de em um valor qualquer. Usaremos para isso uma funo e a chamaremos de 'reajusta': //---------------------------------------------------------------------#include <vcl.h> #pragma hdrstop #include "Unit1.h" //---------------------------------------------------------------------#pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; //---------------------------------------------------------------------void reajusta(float& v, float& r) { v = v * (1 + r / 100); } __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //---------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender) { float vREF, rREF; vREF = StrToFloat(Edit1->Text); rREF = StrToFloat(Edit2->Text); reajusta(vREF ,rREF ); Edit1->Text = FormatFloat("#,##0.00;;Zero",vREF);

} //---------------------------------------------------------------------Neste exemplo podemos ver que usamos a varivel vREF, porm a funo coloca o valor na varivel v. Na verdade o smbolo & avisa que vREF a referncia de v e o valor novo colocado na varivel que for passada como argumento. No exemplo seguinte faremos o uso de ponteiros e atravs do operador de ponteiros & (que colocado antes da varivel) podemos entender o uso de ponteiros. //---------------------------------------------------------------------#include <vcl.h> #pragma hdrstop #include "Unit1.h" //---------------------------------------------------------------------#pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; //---------------------------------------------------------------------void reajusta(float *v, float *r) { *v = *v * (1 + *r / 100); } __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //---------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender) { float vREF, rREF; vREF = StrToFloat(Edit1->Text); rREF = StrToFloat(Edit2->Text); reajusta(&vREF ,&rREF ); Edit1->Text = FormatFloat("R$#,##0.00;;Zero",vREF); } //----------------------------------------------------------------------

Neste exemplo fica evidente o uso de ponteiros. a instruo reajusta(&vREF ,&rREF ); passa para a funo o endereo das variveis atravs do operador & e no os valores. A funo, por sua vez, aponta suas variveis para o endereo das variveis passadas como argumento. Para exemplificar melhor preste ateno no exemplo abaixo: void __fastcall TForm1::Button1Click(TObject *Sender) { int x = 5, y = 10, *px, *py; px = &x; py = &y; } A forma de declarar bem malevel, como pode-se perceber. Aps as instrues a sada ser a seguinte: px py x y = = = = &x &y *x *y 0xfff4 0xfff2 4 7

Da entende-se que x* sinaliza que refere-se ao valor da varivel que est no endereo contido em x, bem como acontece em y.

Marizes e ponteiros
Matrizes e ponteiros esto to relacionados que deveriam ser tratados juntos. A arquitetura dos compiladores entendem ponteiros e no matrizes ento o compilador transforma as matrizes em ponteiros na compilao. O nome de uma matriz representa seu endereo de memria, o primeiro endereo da matriz. Para exemplificar, analisaremos o exemplo abaixo: void __fastcall TForm1::Button2Click(TObject *Sender) { int M[3]={10,20,30}; ListBox1->Clear(); for (int i = 0; i <3; i++) { ListBox1->Items->Add(IntToStr(M[i]) + " - " + IntToStr(*(M+i))); } } Neste caso, teremos como sada no ListBox: (10 - 10, 20 - 20, 30 - 30). Percebemos que M[i] em o mesmo valor que *(M+i). Sem o uso de * teremos o endereo da varivel apontada. moleza!!!!! Vale salientar que assim como existem tipos variveis e constantes existem ponteiros

variveis e ponteiros constantes. Portanto no pode-se utilizar o operador de incremento porque o nome de uma matriz um ponteiro constante. Entende-se ento que o comando (M+ +) est errado. Vamos reescrever o cdigo acima utilizando ponteiro varivel: void __fastcall TForm1::Button2Click(TObject *Sender) { int M[3]={10,20,30}; int *p = M; ListBox1->Clear(); for (int i = 0; i <3; i++) { ListBox1->Items->Add(IntToStr(M[i]) + " - " + IntToStr(*(p++))); } } Desta forma estamos alterando diretamente o endereo da varivel atravs de p. Estamos utilizando ento um ponteiro varivel fazendo valer o processo impossvel no caso anterior.

Funes em C/C++
Imaginem um processo que desenha um boto na tela. J pensou em ter que digitar todo o processo em cada parte em que o programa solicite o desenho do bendito boto? Tudo bem! Voc pode usar o Ctrl+C, Ctrl+V. Mas e para organizar isso tudo? E se for necessrio alterar uma linha de instruo apenas? Ser necessrio fazer em todas? Imaginem o tamanho dessa jossa!!!!! Por isso os Gnios da informtica inventaram as funes. Uma funo uma rotina isolada que pode ser chamada a qualquer momento e que retorna um valor ou no. As funes tem o propsito de dividir o programa em diversos sub-programas e isso facilita a visualizao e organiza o cdigo alm de diminuir o tamanho do programa executvel. Um exemplo de funo a funo main() que a funo principal do C. necessrio que exista uma funo chamada main() para o compilador interpret-la. Para exemplificar, vamos estudar uma funo que converte graus Fahrenheit graus Celsious: //---------------------------------------------------------------------#include <vcl.h> #pragma hdrstop #include "Unit1.h" //---------------------------------------------------------------------#pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; //----------------------------------------------------------------------

__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } int celsius(int fahrenheit) { int var; var = (fahrenheit - 32) * 5/9; return var; } //---------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender) { Edit1->Text = IntToStr(celsius(StrToInt(Edit1->Text))); } //---------------------------------------------------------------------No caso acima fazemos a chamada da funo dentro de uma outra funo. A IntToStr(), que converte nmeros inteiros para uma cadeia de caracteres, e passamos como parmetro uma outra funo que faz o inverso convertendo a string contida no EditBox em nmero inteiro. O corpo da funo est dentro da linha pontilhada que aloca a funo main(). Por isso no foi preciso declar-la. Porm se ela estivesse fora desse meio (como geralmente acontece) seria necessrio declar-la. O valor convertido passado atravs da funo return. Veja o exemplo: //---------------------------------------------------------------------#include <vcl.h> #pragma hdrstop #include "Unit1.h" //---------------------------------------------------------------------#pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; //---------------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //-----------------------------------------------------------

-----------void __fastcall TForm1::Button1Click(TObject *Sender) { int celsius(int fahrenheit); Edit1->Text = IntToStr(celsius(StrToInt(Edit1->Text))); } //---------------------------------------------------------------------int celsius(int fahrenheit) { int var; var = (fahrenheit - 32) * 5/9; return var; } //---------------------------------------------------------------------No exemplo acima, existe a chamada (prottipo local) funo no evento OnClick do boto (Isso ser melhor explicado no futuro). A chamada poderia estar tambm logo acima ou abaixo da funo main() (prottipo externo). As funes do tipo void so funes que no retornam nada Para se passar vrios argumentos em uma funo basta declarar todos eles. Ex: //---------------------------------------------------------------------#include <vcl.h> #pragma hdrstop #include "Unit1.h" //---------------------------------------------------------------------#pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; //---------------------------------------------------------------------int AreaRetangulo(int l1, int l2); __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //----------------------------------------------------------------------

void __fastcall TForm1::Button1Click(TObject *Sender) { int l11, l22, area; l11 = StrToInt(Edit1->Text); l22 = StrToInt(Edit2->Text); area = AreaRetangulo(l11, l22); Label1->Caption = "A rea do quadrado " + IntToStr(area); } //---------------------------------------------------------------------int AreaRetangulo(int l1, int l2) { int area = l1 * l2; return area; } //---------------------------------------------------------------------Como um usurio abelhudo pode deixar de passar argumentos, voc pode ter valores default nas funes simplesmente dando valores s variveis na declarao das mesmas logo na chamada da funo. Voc pode tambm criar funes com o mesmo nome e mudar somente tipo do argumento. Dessa forma haver a chamada sobrecarga de funes e um timo exemplo de polimorfismo.

Funes e matrizes como argumentos


Observe o cdigo fonte abaixo: //---------------------------------------------------------------------#include <vcl.h> #pragma hdrstop #include "Unit1.h" //---------------------------------------------------------------------#pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; //---------------------------------------------------------------------void reajusta(float *v, float r, int Qtde) { for (int i=0; i<Qtde; i++) *v++ = *v * (1 + r / 100); }

__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //---------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender) { AnsiString InputString = ListBox1->Items>Add(FormatFloat("#,##0.00;;Zero", StrToFloat(InputBox("Input Box", "Valor em R$", "10,00")))); } //---------------------------------------------------------------------void __fastcall TForm1::Button2Click(TObject *Sender) { const MAX=50; //n mximo de variveis float vREF[MAX]; for (int i=0; i<ListBox1->Items->Count; i++) vREF[i] = StrToFloat(ListBox1->Items->Strings[i]); reajusta(vREF ,StrToFloat(Edit1->Text), ListBox1->Items>Count); for (int i=0; i<ListBox1->Items->Count; i++) ListBox2->Items>Add(FormatFloat("R$#,##0.00;;Zero",vREF[i])); } //-------------------------------------------------------------------------Se voc prestar ateno, facilmente entende como trabalhar com matrizes e ponteiros junto com funes. Na funo, utiliza-se o operador * para sinalizar a varivel que a funo precisa alterar enquanto que as outras servem apenas para realizar o clculo. O argumento passado simplesmente citando a varivel (note que no necessrio digitar o nmero de array) matriz e pode-se utilizar essa matriz logo aps a funo tendo os valores devidamente alterados. Moleza!!!!!

Funes inline
Se o comando inline estiver precedendo uma funo, significa que o compilador ir copila para cada parte do programa onde ela chamada. vlido para o caso de funes pequenas e de pouco uso porque voc estar poupando tempo de execuo j que no haver a necessidade de se locomover do controle para o cdigo da funo.

Funes recursivas

So funes que chama a si prpria. Vamos exemplificar com a situao mais bvia da recurso. Uma funo que calcula o fatorial de um nmero. //---------------------------------------------------------------------#include <vcl.h> #pragma hdrstop #include "Unit1.h" //---------------------------------------------------------------------#pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; //---------------------------------------------------------------------long Fatorial(int numero); __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //---------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender) { Edit1->Text = IntToStr(Fatorial(StrToInt(Edit1->Text))); } //---------------------------------------------------------------------long Fatorial(int numero) { return ( (numero==0) ? long(1) : long(numero) * Fatorial(numero-1)); } //---------------------------------------------------------------------A funo Fatorial usa o operador ternrio ? : . Este operador precisa de trs operandos (uma condio e duas instrues) e funciona da seguinte forma: O primeiro operando uma condio. Se ela for maior que 0 (portanto verdadeira) executa a segunda instruo que o terceiro operando. Se ela for 0 (portanto falsa) executa a primeira instruo que o segundo operando. A recursividade est no jeito como essa funo tratada pelo compilador. Como ele no pode substituir a sub-funo por valores reais e executar os clculos necessrios o compilador

aloca os valores na memria at chegar em um ponto que exista uma condio que gere valores reais. Assim possvel comear a calcular todo o processo. Seria mais ou menos como se fossem criada outras funes no lugar das sub-funes. Por exemplo se o nmero fosse 3: long Fatorial(3) { return ( (3==0) ? long(1) : long(3) * Fatorial2(2)); } long Fatorial2(2) { return ( (2==0) ? long(1) : long(2) * Fatorial3(1)); } long Fatorial3(1) { return ( (1==0) ? long(1) : long(1) * Fatorial4(1)); } long Fatorial4(0) { return ( (0==0) ? long(1); }

Arquivos binrios
Para se trabalhar com arquivos usa-se, em C++, um objeto stream, das classes iostream. Stream significa "fluxo de caracteres". importante considerar no somente os arquivos em disco mas tambm os dispositivos de entrada e sada, inclusive as portas para se trabalhar com as classes iostream. As classes usadas para leitura e gravao de discos so declaradas no arquivo FSTREAM.H, que j inclui o arquivo IOSTREAM.H, tambm utilizado para manipular bytes em geral.

Hierarquia das classes stream


O diagrama a seguir serve para mostrar quais classes esto contidas em quais classes. Desta forma, fica mais fcil aplicar uma dessas classes j conhecendo suas derivadas.

A tabela a seguir detalha os arquivos e as classes contidas: Arquivo Classes contidas ios streambuf istream ostream istream_withassign Iostream_init ostream_withassign filebuf ifstream fstream ofstream istrstream ostrstream strstream strstreambuf stdiobuf stdiostream

iostream.h

fstream.h

strstrea.h

stdios.h

No adiantaria nada comear a citar as classes e respectivas funes. Ao contrrio, s complicaria a nossa compreenso principalmente porque nesse momento o conceito de

classes e orientao a objeto no est completamente fundamentada. Para exemplificar algumas classes iremos ento criar programas exemplo. O primeiro deles ser um verificador de atributos de arquivos. Crie um formulrio semelhante ao que segue e redija o cdigo completo que segue abaixo:

//-------------------------------------------------------------------------#include <vcl.h> #include <Dialogs.hpp> #include <filectrl.hpp> #pragma hdrstop AnsiString arquivo;//inicio do arquivo; int atrib; #include "main.h" //-------------------------------------------------------------------------#pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; //-------------------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } soma(int x, int y) {

return x+y ; } //-------------------------------------------------------------------------void __fastcall TForm1::BitBtn2Click(TObject *Sender) { /************************************************** *passa o nome do arquivo que tiver no edit1 para * * a varivel * **************************************************/ arquivo=nomearq->Text; /************************************************** * passa o atributo do arquivo para a varivel * * atrib * **************************************************/ atrib=FileGetAttr(arquivo); /************************************************** *verifica qual o atributo do arquivo e seleciona o* *componente checkbox * **************************************************/ if ((atrib & faReadOnly)==faReadOnly){ //se for somente leitura sl->Checked=true; } else sl->Checked=false; if ((atrib & faHidden)==faHidden) { //se for oculto oc->Checked=true; } else oc->Checked=false; if ((atrib & faSysFile)==faSysFile){ //se for de sistema si->Checked=true; } else si->Checked=false; if ((atrib & faArchive)==faArchive) { //se for arquivo ar->Checked=true; } else ar->Checked=false; } //-------------------------------------------------------------------------void __fastcall TForm1::BitBtn3Click(TObject *Sender) { atrib=0; // zera os atributos // verifica qual atributo est selecionado e passa o atributo

para a varivel if (sl->Checked==true) atrib=(atrib | faReadOnly); if (oc->Checked==true) atrib=(atrib | faHidden); if (si->Checked==true) atrib=(atrib | faSysFile); if (ar->Checked==true) atrib=(atrib | faArchive); FileSetAttr(arquivo,atrib); } //-------------------------------------------------------------------------O exemplo utiliza as classes fstream, ifstream e ofstream para manipulao de arquivos. Essas classes esto contidas no arquivo filectrl.hpp, que derivado delas. Vamos fazer um outro exemplo para arquivos de texto. Faa um formulrio semelhante e redija o cdigo fonte correspondente:

//--------------------------------------------------------------------------

#include <vcl.h> #pragma hdrstop #include "main.h" //-------------------------------------------------------------------------#pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; //-------------------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //-------------------------------------------------------------------------void __fastcall TForm1::BitBtn1Click(TObject *Sender) { /************************************************************ ********* * Carregando a arquivo de texto * ************************************************************* ********/ Memo1->Lines->LoadFromFile(FileListBox1->FileName); } //-------------------------------------------------------------------------void __fastcall TForm1::BitBtn3Click(TObject *Sender) { Memo1->Lines->Clear(); } //-------------------------------------------------------------------------void __fastcall TForm1::BitBtn2Click(TObject *Sender) { /************************************************************ * Apresenta a caixa de dilogo salvar * ************************************************************/ if (SaveDialog1->Execute()) {

/************************************************************ * Salva o arquivo * ************************************************************/ Memo1->Lines->SaveToFile(SaveDialog1->FileName+".txt"); FileListBox1->Update(); } } //-------------------------------------------------------------------------Este foi um programa editor de texto e pode-se ver como a ferramenta da borland nos priva de trabalho desnecessrio e que nos aborrece demais. extremamente simples carregar um arquivo texto no C++ builder, assim como no delphi.

Estruturas
Em programao, a evoluo trata-se sempre de contextualizao (pelo menos at hoje) o que significa que o bruto no muda muita coisa. No fundo, tudo no passa de 0's e 1's. As coisas mudam sempre acompanhando a evoluo da capacidade de processamento porque, quando temos ciclos e memria de sobra, podemos explorar ao mximo nossa capacidade de organizao e implementao. Ento, no decorrer do tempo, foram criados certos "conceitos" que nos permitiram criar novas formas de implementar um cdigo (formas essas mais seguras e organizadas, alm de fceis). Ento criou-se novas ferramentas da nem nos preocupamos em pensar como ela funciona de verdade. Ns simplesmente as utilizados. A estrutura uma ferramenta desse tipo, implementada nas linguagens de programao permitindo que criemos variveis complexas facilitando a forma de manipular essa variveis conforme nossa necessidade. Dessa forma podemos formar um conjunto de variveis (chamadas de membros) que podem ser dos tipos que j conhecemos. As estruturas lhe permitem ento agrupar itens de dados. Portanto, entender estruturas meio caminho andado para entender classes (que agrupam alm de itens de dados, funes). A sintaxe de uma estrutura a seguinte: struct nome { : float int AnsiString : };

var1; var2; var3;

Onde nome o nome da estrutura e as chaves contm a a seqncia de variveis. Para entender toda essa ladainha vamos a uma aplicao prtica: #include <vcl.h> #pragma hdrstop

#include "Unit1.h" //-------------------------------------------------------------------------#pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; struct Aluno { int Mat; float Nota[4]; float Media; }; //-------------------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //-------------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender) { int i = 0; float media = 0; Aluno Godofredo; Godofredo.Mat = StrToInt(InputBox("Entrada de dados", "Matcula", "1")); do { Godofredo.Nota[i] = StrToFloat(InputBox("Entrada de dados","Nota " + IntToStr(i+1), "1")); media = media + Godofredo.Nota[i++]; }while (i<=3); Godofredo.Media = media / 4; ListBox1->Items->Add(FloatToStr(Godofredo.Media)); } //-------------------------------------------------------------------------No exemplo observamos uma varivel do tipo novo de nome Aluno. Dentro desse tipo esto outros 3 tipos distintos que podem ser acessados atravs do caractere ponto ".". Essas variveis ficam encapsulados dentro do tipo aluno e s podem ser acessados atravs dele. Porm no passam de variveis comuns acessadas em qualquer parte do programa. Valem todas as regras anteriores para tratamento de variveis. Pode-se declar-las juntamente com a estrutura:

struct Aluno { int Mat; float Nota[4]; float Media; } Ana, Godofredo, Patrcia; Inicializ-las junto a declarao podendo simplesmente omitir algum membro: Aluno Godofredo = {1,{4,3.1,5,8} ,}; Atribuies: Aluno Godofredo = {1,{4,3.1,5,8} ,}, Geraldo; Geraldo = Godofredo; Ou mesmo aninh-las: struct Data { int Dia; AnsiString Mes[10]; int Ano; }; struct Vendas { int Pecas; float Preco; data DiaVenda; }; Para inicializar uma estrutura aninhada, basta tratar a estrutura mais interna como se fosse uma matriz, colocando os valores dentro das chaves "{}". Em relao aos operadores deve-se tomar cuidado. Tomando como exemplo o operador de soma "+", podemos imaginar que para somar dois tipos estruturados diferentes basta aplicar o oprador e isso no ;e verdade. Veja o exemplo: Total = A + B; //Errado Total.Pecas = A.Pecas + B.Pecas; Total.Preco = A.Preco + B.Preco; Pode-se tambm passar estruturas como argumentos de funes da mesma forma como era feito antigamente: //--------------------------------------------------------------------------

#include <vcl.h> #pragma hdrstop #include "Unit1.h" //-------------------------------------------------------------------------#pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; struct Aluno { int Mat; float Nota[4]; float Media; }; struct Data { int Dia; AnsiString Mes[10]; int Ano; }; struct Venda { int Pecas; float Preco; Data DiaVenda; }; Venda Soma(Venda a2, Venda b2) { Venda Total2; Total2.Pecas = a2.Pecas + b2.Pecas; Total2.Preco = a2.Preco + b2.Preco; return Total2; } //-------------------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //-------------------------------------------------------------------------void __fastcall TForm1::Button2Click(TObject *Sender) {

Venda a, b, Total; a.Pecas = StrToInt(InputBox("Entrada de dados", "Pecas", "1")); a.Preco = StrToFloat(InputBox("Entrada de dados", "Preco", "1")); b.Pecas = StrToInt(InputBox("Entrada de dados", "Pecas", "1")); b.Preco = StrToFloat(InputBox("Entrada de dados", "Preco", "1")); Total = Soma(a, b); Edit1->Text = IntToStr(Total.Pecas); Edit2->Text = FloatToStr(Total.Preco); } //-------------------------------------------------------------------------Pode-se tambm, obviamente, declarar variveis que sejam do tipo de uma estrutura e sejam matrizes. Venda vd[10], Total; acessando ela da seguinte forma: a[n].Preo;

Classes
Agora que conhecemos os tipos estruturados, podemos entrar em classes conscientes de sua importncia para o programador ps-moderno. Diferente das estruturas, o objetivo principal de uma classe englobar no s as variveis de um sistema de dados mas tambm suas funes e procedimentos. A partir da, criou-se todo um conceito para melhor atender a essa necessidade e aprimorou-se a linguagem de programao orientada a objeto nesse sentido. Agora que temos dentro de nosso sistema variveis (propriedades) e funes (mtodos), podemos "sonhar" em manipular operadores e trabalhar com herana e polimorfismo Todos eles presentes com suas particularidades em cada classe. Vamos comear do comeo e implementar nossa primeira classe, de forma bem simples: //-------------------------------------------------------------------------#include <vcl.h> #pragma hdrstop class Aluno { private: int Mat;

public: float Nota[4]; void EfetuarMat(int MatTemp) {Mat = MatTemp;} float Media() { return (Nota[0] + Nota[1] + Nota[2] + Nota[3]) / 4; } }; #include "Unit1.h" //-------------------------------------------------------------------------#pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; //-------------------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //-------------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender) { Aluno Julia, Ana; Ana.EfetuarMat(StrToInt(InputBox("Entrada de dados", "Matrcula","1"))); Ana.Nota[0] = StrToFloat(Edit1->Text); Ana.Nota[1] = StrToFloat(Edit2->Text); Ana.Nota[2] = StrToFloat(Edit3->Text); Ana.Nota[3] = StrToFloat(Edit4->Text); float x = Ana.Media(); Edit5->Text = FormatFloat("#,##0.00;;Zero",x); } //-------------------------------------------------------------------------Basicamente, podemos considerar as propriedades de um objeto como as variveis de uma estrutura e os mtodos (funes membro) como funes internas da classe. As funesmembro ou mtodos dentro da declarao da classe so consideradas inline por default mas podem ser implementadas fora da classe desde que seja declarada dentro dela. Por exemplo: class Aluno { private:

int Mat; public: float Nota[4]; void EfetuarMat(int MatTemp) {Mat = MatTemp;} float Media(); }; float Aluno::Media() { return (Nota[0] + Nota[1] + Nota[2] + Nota[3]) / 4; } Apareceram tambm dois termos novos alm da palavra chave "class", que so o private e o public. Uma estrutura, por defaut tem todos seus membros pblicos.Porm, pode declarar membros privados. No caso de classes, costuma-se declarar as variveis como private e as funes membros (mensagens ou mtodos) como public. Dessa forma, evita-se instrues equivocadas que alterem erroneamente alguma propriedade da classe. Voltemos ao nosso exemplo: Ele implementa em uma classe o que j havamos visto na aula passada. Porm agora a funo Media() foi incorporada classe. Isso poderia ter sido feito com estruturas mas a maioria dos programadores em C++ utilizam sempre as classes quando querem implementar algum mtodo aos seus sistemas.

Classes, objetos e instncias


Agora precisamos esclarecer isso antes que vire dvida. Uma classe definida no significa que um objeto foi definido. Ela simplesmente indica a possibilidade da criao de um objeto. A existncia de um objeto, por sua vez, no indica a existncia de uma instncia. Ento percebemos que um objeto completamente subjetivo. Como assim? Bom: Um objeto a classe padro criada. Uma instncia um objeto especfico, um componente e suas particularidades. Por exemplo: Uma caixa de texto (TEdit) um objeto derivado da classe TCustomEdit. O Edit1 a instncia do objeto TEdit e o Edit2 outra instncia em um form. Quem define a classe a palavra chave class e sua sintaxe a seguinte: class NomeDaClasse { private: Membros public: Membros pblicos Funes-membro (Mtodos) };

Para criar um objeto, assim como um tipo complexo de uma estrutura, basta declar-lo como se fosse um tipo de varivel: Aluno Julia, Ana; O caractere ponto "." que da acesso aos mtodos da classe. Atravs dele podemos mandar uma "mensagem" para a instncia: Ana.EfetuarMat(StrToInt(InputBox("Entrada de dados", "Matrcula","1"))); Ana.Nota[0] = StrToFloat(Edit1->Text); Ana.Nota[1] = StrToFloat(Edit2->Text); Ana.Nota[2] = StrToFloat(Edit3->Text); Ana.Nota[3] = StrToFloat(Edit4->Text); Observe que a propriedade Nota[] pblica. Ento pode-se simplesmente atribuir um valor a ela. Isso no acontece com a varivel Mat, que privada. Para resolver isso, foi criado o mtodo EfetuarMat() que uma funo interna da classe que tem acesso varivel e que de fato a modifica. Dizemos ento que enviamos uma mensagem ao objeto.

Construtores
Quando existe um mtodo com o mesmo nome de uma classe, ento trata-se de um mtodo de execuo automtica na criao de uma instncia. Dizemos ento que este mtodo um construtor. Ex: //-------------------------------------------------------------------------#include <vcl.h> #pragma hdrstop class Aluno { private: int Mat; public: float Nota[4]; Aluno(int MatTemp) { Mat = MatTemp; Nota[0] = Nota[1] = Nota[2] = Nota[3] = 0; } float Media() { return (Nota[0] + Nota[1] + Nota[2] + Nota[3]) / 4; } };

#include "Unit1.h" //-------------------------------------------------------------------------#pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; //-------------------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //-------------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender) { Aluno Julia(1), Ana(2); Ana.Nota[0] = StrToFloat(Edit1->Text); Ana.Nota[1] = StrToFloat(Edit2->Text); Ana.Nota[2] = StrToFloat(Edit3->Text); Ana.Nota[3] = StrToFloat(Edit4->Text); float x = Ana.Media(); Edit5->Text = FormatFloat("#,##0.00;;Zero",x); } //-------------------------------------------------------------------------Desta forma precisamos gerar o nmero de matrcula de uma instncia (aluno) logo em sua declarao: Aluno Julia(1), Ana(2); O mtodo responsvel por essa inicializao automtica o aluno que evidentemente poderia ser implementado fora da classe desde que declarado dentro dela: class Aluno { private: int Mat; public: float Nota[4]; Aluno(int MatTemp); float Media() { return (Nota[0] + Nota[1] + Nota[2] + Nota[3]) / 4; }

}; Aluno::Aluno(int MatTemp) { Mat = MatTemp; Nota[0] = Nota[1] = Nota[2] = Nota[3] = 0; } importante salientar tambm que um construtor no deve retornar valor algum, pois trata-se de uma funo especfica de inicializao (da o nome construtor). Agora, voc pode querer, evidentemente, manter a opo de criar uma instncia sem necessariamente inicializar os dados dela. Para isso voc pode fazer uma sobrecarga de construtores: //-------------------------------------------------------------------------#include <vcl.h> #pragma hdrstop class Aluno { private: int Mat; public: float Nota[4]; Aluno() { Mat = StrToInt(InputBox("Entrada de dados", "Matrcula","1")); } Aluno(int MatTemp) { Mat = MatTemp; Nota[0] = Nota[1] = Nota[2] = Nota[3] = 0; } float Media() { return (Nota[0] + Nota[1] + Nota[2] + Nota[3]) / 4; } }; #include "Unit1.h" //-------------------------------------------------------------------------#pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; //--------------------------------------------------------------------------

__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //-------------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender) { Aluno Julia(1), Ana; Ana.Nota[0] = StrToFloat(Edit1->Text); Ana.Nota[1] = StrToFloat(Edit2->Text); Ana.Nota[2] = StrToFloat(Edit3->Text); Ana.Nota[3] = StrToFloat(Edit4->Text); float x = Ana.Media(); Edit5->Text = FormatFloat("#,##0.00;;Zero",x); } //-------------------------------------------------------------------------Dessa forma, quando uma classe for inicializada sem valores, ser executada a funomembro Aluno(). Ela chama a funo InputBox automaticamente para solicitar ao usurio o nmero de matrcula do aluno, mas poderia simplesmente no ter instruo alguma. As funes-membro podem ainda ser constantes: Para isso, deve preceder a palavra const em sua declarao. Dessa forma, o usurio pode criar uma instncia constante (somente para leitura) e a classe s poder utilizar as funes-membro que forem declaradas como constantes. Por exemplo: //-------------------------------------------------------------------------#include <vcl.h> #pragma hdrstop class Aluno { private: int Mat; public: float Nota[4]; Aluno() {} Aluno(int MatTemp) { Mat = MatTemp; Nota[0] = Nota[1] = Nota[2] = Nota[3] = 0; } float Media() const { return (Nota[0] + Nota[1] + Nota[2] + Nota[3]) / 4;

} }; #include "Unit1.h" //-------------------------------------------------------------------------#pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; //-------------------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //-------------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender) { const Aluno Julia(1), Ana; float x = Ana.Media(); Edit5->Text = FormatFloat("#,##0.00;;Zero",x); } //-------------------------------------------------------------------------Assim, a instncia s poder utilizar o mtodo mdia(). Alm se poder ser constante, uma funo membro pode, obviamente, utilizar objetos como argumentos declarados normalmente e retornar objetos tambm.

Propriedades static
Quando uma instncia de aluno criada temos que fornecer o n de matrcula, certo? Mas isso no muito bom!! Seria melhor se o n de matrcula fosse incrementado automaticamente quando a instncia fosse criada. Para isso, pode-se utilizar de propriedades static. Uma propriedade static uma varivel comum, porm comum a todas as instncias, ou seja, um nico valor para todos os objetos criados, de forma que s destruda quando o o ltimo objeto "tirado" da memria e criada quando o primeiro objeto colocado na memria. E todas as instncias podem acess-lo, o que significa que o valor pode ser recuperado a partir de qualquer um dos objetos criados. Observe o cdigo a seguir:
//--------------------------------------------------------------------------#include <vcl.h> #pragma hdrstop #include "Unit1.h" //--------------------------------------------------------------------------#pragma package(smart_init) #pragma resource "*.dfm" class RETANGULO

{ private: int BASE, ALTURA; static int CONT; public: RETANGULO(int b, int h) //Construtor. { CONT++; BASE = b; ALTURA = h; } RETANGULO(void) //Construtor sobrecarregado. { CONT++; BASE = StrToInt(InputBox("Entrada","Digite a base do retngulo " + IntToStr(CONT),"")); ALTURA = StrToInt(InputBox("Entrada","Digite a altura do retngulo " + IntToStr(CONT),"")); } ~RETANGULO(void) //Destrutor. { CONT--; } int Area(void) { return BASE * ALTURA; } int QtdeDeObjetos(void) { return CONT; } void Desenhar(TImage *Componente, int PosX, int PosY) { Componente->Canvas->Rectangle(PosX, PosY, PosX + BASE, PosY + ALTURA); } }; int RETANGULO::CONT = 0; TForm1 *Form1; //--------------------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //--------------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender) { RETANGULO A; A.Desenhar(Image1, StrToInt(Edit1->Text),StrToInt(Edit2->Text)); } //--------------------------------------------------------------------------void __fastcall TForm1::Button2Click(TObject *Sender) { RETANGULO A, B(70,70),C(50,50); A.Desenhar(Image1, StrToInt(Edit1->Text),StrToInt(Edit2->Text)); B.Desenhar(Image1, StrToInt(Edit1->Text),StrToInt(Edit2->Text)); C.Desenhar(Image1, StrToInt(Edit1->Text),StrToInt(Edit2->Text)); } //--------------------------------------------------------------------------void __fastcall TForm1::Button3Click(TObject *Sender) { RETANGULO A[5]; for (int i= 0; i <= 4; i++) {

A[i].Desenhar(Image1, StrToInt(Edit1->Text)+ 5 * i,StrToInt(Edit2->Text)+ 5 * i); } } //---------------------------------------------------------------------------

Estamos vendo coisas diferentes nesse programa: A linha de comando static int CONT; cria a propriedade esttica CONT, que ser comum a todos os objetos do tipo RETANGULO criados no programa. A linha de comando: int RETANGULO::CONT = 0; simplesmente inicializa a propriedade uma vez que no podemos fazer isso dentro da classe. Outra novidade a utilizao de um componente como argumento de uma funo:
A[i].Desenhar(Image1, StrToInt(Edit1->Text)+ 5 * i,StrToInt(Edit2->Text)+ 5 * i);

Dessa forma voc pode mandar uma mensagem funo dizendo onde est o componente que deseja alterar (como ponteiro) da seguinte forma:
void Desenhar(TImage *Componente, int PosX, int PosY) { Componente->Canvas->Rectangle(PosX, PosY, PosX + BASE, PosY + ALTURA); }

Variveis extern
Podemos tambm criar uma varivel global fora da classe. Lembramos que se uma varivel for declarada em um arquivo .h (header), e esse arquivo for includo em nosso cdigo (#include), ento ela estar disponvel no nosso cdigo. A desvantagem e que ela estar criada mesmo que no exista objeto algum criado, ocupando espao desnecessrio na memria. Vamos aplicar esse exemplo ao nosso antigo problema: //-------------------------------------------------------------------------#include <vcl.h> #pragma hdrstop int n = 0; class Aluno { private: int Mat; float Nota[4]; public: Aluno() { Mat = n; n++; Nota[0] = Nota[1] = Nota[2] = Nota[3] = 0; } float Media()

{ return (Nota[0] + Nota[1] + Nota[2] + Nota[3]) / 4; } int NumMat() {return Mat;} int TotalMat() {return n;} }; #include "Unit1.h" //-------------------------------------------------------------------------#pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; //-------------------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //-------------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender) { Aluno Ana, Julia; Edit1->Text = FormatFloat("#,##0.00;;Zero",Ana.Media()); ListBox1->Items->Add(IntToStr(Ana.NumMat()) + " - " + IntToStr(Ana.TotalMat())); ListBox1->Items->Add(IntToStr(Julia.NumMat()) + " - " + IntToStr(Julia.TotalMat())); } //-------------------------------------------------------------------------Nesse cdigo, a varivel n incrementada a cada criao de instncia e gera o nmero de matrcula a partr desse nmero.

Destrutores
Ainda assim, precisamos prever a destruio de uma instncia, certo? Para isso usaremos um mtodo chamado destrutor: //-------------------------------------------------------------------------#include <vcl.h> #pragma hdrstop int n;

class Aluno { private: int Mat; float Nota[4]; public: Aluno() { Mat = n++; } ~Aluno() { n--; } float Media() { return (Nota[0] + Nota[1] + Nota[2] + Nota[3]) / 4; } int NumMat() {return Mat;} int TotalMat() {return n;} }; #include "Unit1.h" //-------------------------------------------------------------------------#pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; //-------------------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //-------------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender) { Aluno Ana, Julia; Edit1->Text = FormatFloat("#,##0.00;;Zero",Ana.Media()); ListBox1->Items->Add(IntToStr(Ana.NumMat()) + " - " + IntToStr(Ana.TotalMat())); ListBox1->Items->Add(IntToStr(Julia.NumMat()) + " - " + IntToStr(Julia.TotalMat())); { Aluno Joao, Maria; ListBox1->Items->Add(IntToStr(Joao.NumMat()) + " - " +

IntToStr(Joao.TotalMat())); ListBox1->Items->Add(IntToStr(Maria.NumMat()) + " - " + IntToStr(Maria.TotalMat())); } Edit1->Text = IntToStr(Ana.TotalMat()); } //-------------------------------------------------------------------------O destrutor de uma classe o mtodo que leva o nome da classe precedido de "~", np caso, o mtodo ~Aluno(). Em nosso exemplo, o destrutor decrementa a varivel externa n para que ela contenha sempre o nmero de instncias criadas. As instncias criadas entre as chaves so automaticamente destrudas no termino das chaves e a execuo do exemplo pode nos mostrar isso.

Matrizes de objetos
Por fim, assim como qualquer tipo de variveis ou estrutura, podemos declarar uma matriz de objetos que contenha vrias instncias. //-------------------------------------------------------------------------#include <vcl.h> #pragma hdrstop int n; class Aluno { private: int Mat; AnsiString Nome; float Nota[4]; public: Aluno () {Mat = n++;} ~Aluno() {n--;} float Media() { return (Nota[0] + Nota[1] + Nota[2] + Nota[3]) / 4; } void LancarNotas() { Nome = InputBox("Entrada de dados","Nome do aluno:",""); for (int i = 0; i<=3; i++) Nota[i] = StrToInt(InputBox("Entrada de dados",IntToStr(i+1) + "

Nota","0")); } float RetornaNota(int i) {return Nota[i];} AnsiString RetornaNome(void) {return Nome;} int NumMat() {return Mat;} int TotalMat() {return n;} }; #include "Unit1.h" //-------------------------------------------------------------------------#pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; //-------------------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //-------------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender) { const int n = 2; Aluno DSC37x[n]; for (int i = 0; i<n; i++) DSC37x[i].LancarNotas(); for (int i = 0; i<n; i++) { ListBox1->Items->Add(DSC37x[i].RetornaNome() + " -> " + IntToStr(DSC37x[i].NumMat()) + " - Notas: [" + FormatFloat("#,##0.00, ;;Zero",DSC37x[i].RetornaNota(0)) + FormatFloat("#,##0.00, ;;Zero",DSC37x[i].RetornaNota(1)) + FormatFloat("#,##0.00, ;;Zero",DSC37x[i].RetornaNota(2)) + FormatFloat("#,##0.00, ;;Zero",DSC37x[i].RetornaNota(3)) + "] - Media: " + FormatFloat("#,##0.00;;Zero",DSC37x[i].Media())); } } //-------------------------------------------------------------------------At aqui no nenhum segredo mas e se quisssemos definir a quantidade de alunos em tempo de execuo. Seria possvel? Seria! E serve para qualquer situao. Veja o exemplo abaixo:

//-------------------------------------------------------------------------#include <vcl.h> #pragma hdrstop int n; class Aluno { private: int Mat; AnsiString Nome; float Nota[4]; public: Aluno () {Mat = n++;} ~Aluno() {n--;} float Media() { return (Nota[0] + Nota[1] + Nota[2] + Nota[3]) / 4; } void LancarNotas() { Nome = InputBox("Entrada de dados","Nome do aluno:",""); for (int i = 0; i<=3; i++) Nota[i] = StrToInt(InputBox("Entrada de dados",IntToStr(i+1) + " Nota","0")); } float RetornaNota(int i) {return Nota[i];} AnsiString RetornaNome(void) {return Nome;} int NumMat() {return Mat;} int TotalMat() {return n;} }; #include "Unit1.h" //-------------------------------------------------------------------------#pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; //-------------------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //-------------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender)

{ Aluno (* DSC37x); int n = StrToInt(InputBox("Entrada de dados","Quantidade de alunos","1")); DSC37x = new Aluno [n]; for (int i = 0; i<n; i++) DSC37x[i].LancarNotas(); for (int i = 0; i<n; i++) { ListBox1->Items->Add(DSC37x[i].RetornaNome() + " -> " + IntToStr(DSC37x[i].NumMat()) + " - Notas: [" + FormatFloat("#,##0.00, ;;Zero",DSC37x[i].RetornaNota(0)) + FormatFloat("#,##0.00, ;;Zero",DSC37x[i].RetornaNota(1)) + FormatFloat("#,##0.00, ;;Zero",DSC37x[i].RetornaNota(2)) + FormatFloat("#,##0.00, ;;Zero",DSC37x[i].RetornaNota(3)) + "] - Media: " + FormatFloat("#,##0.00;;Zero",DSC37x[i].Media())); } } //-------------------------------------------------------------------------As seguintes instrues: Aluno (* DSC37x); int n = StrToInt(InputBox("Entrada de dados","Quantidade de alunos","1")); DSC37x = new Aluno [n]; Cuidam disso. O que declarado na primeira instruo no uma matriz e sim um ponteiro. A segunda instruo solicita ao usurio o n de alunos e a terceira reserva o espao em memria necessrio redimensionando a varivel.

Sobrecarga de operadores
J vimos construtores (com sobrecarga) e destrutores, porm quando desenvolvemos uma classe, podemos atribuir processos exclusivos para os operadores!!! E que diabos significa isso? Significa que, por exemplo, podemos fazer um mtodo especial que atue sempre que um objeto criado a partir de nossa classe estiver em uma operao. Por exemplo: Se quisermos somas dois valores inteiros, podemos fazer da seguinte forma: int x = 10, y = 20, soma; soma = x + y; J sabemos que atribuies (=) entre objetos podem ser feitas normalmente (Neste caso, simplesmente copia-se o valor de todas as propriedades). Mas se tentarmos utilizar o

operador de soma (+) com os objetos, ocorrer um erro: Temperatura Obj1, Obj2, ObjSoma; Obj1.EntraTempCelsius(); Obj2.EntraTempCelsius(); ObjSoma = Obj1 + Obj2; Para que o operador de soma (+) funcione em nossa classe, precisamos prever sua utilizao tendo retorno e argumentos (porque o operador uma funo comum) do tipo de nossa classe. Resolveremos isso incluindo um mtodo especial em nossa classe: Temperatura operator + (Temperatura x) { x.TempCelsius = TempCelsius + x.TempCelsius; return x; } Reparem que o nome do mtodo operator +. Lgicamente podemos concluir que para criar um mtodo de outro operador, basta substituir o + pelo operador em questo. A palavra que antecede o nome do mtodo (Temperatura) nada tem a ver com construtores. o retorno do mtodo (assim como int, void ou float). Reparem que x um objeto (que o prprio argumento) criado somente para o mtodo em questo. Maravilha! Agora, a utilizao vai depender unica e exclusivamente da lgica de utilizao do operador. Por exemplo o operador unrio (++): Temperatura operator ++ (void) { Temperatura x; x.TempCelsius = ++TempCelsius; return x; } O mtodo muito parecido com o do operador de soma (+). A diferena que ele no precisa de argumentos porque ele s precisa incrementar a temperatura (que propriedade interna da classe). No caso anterior, era necessrio somar a temperatura com outra aprovvel temperatura ( x + y), no caso a temperatura do objeto y. No caso do incremento (x++), no vem nenhum valor externo. Agora vem um conceito e somente esse operador tem esse tipo de exceo, que no deixa de ter uma certa lgica. O mtodo anterior serve para o operador de pr-incremento. Se quisermos utilizar o operador de ps-incremento, precisamos simplesmente indicar uma declarao int (somente a declarao) dentro dos parnteses de argumentos. O mtodo ficar assim: Temperatura operator ++ (int) { Temperatura x; TempCelsius++;

x.TempCelsius = TempCelsius - 1; return x; } Reparem que precisamos atribuir ao objeto que ser retornado o valor NO incrementado, seno no ser um pr-incremento. Poderia ser assim tambm: Temperatura operator ++ (int) { Temperatura x; x.TempCelsius = TempCelsius++; return x; } Viram que moleza! Agora a nossa classe ficou assim:
class Temperatura { private: float TempCelsius; public: Temperatura (void) { //Inicializa o objeto com a temperatura ambiente mdia. TempCelsius = 23; } void EntraTempCelsius (void) { TempCelsius = StrToFloat(InputBox("Entrada","Temperatura (C):", "0")); } void EntraTempFahr (void) { TempCelsius = (StrToFloat(InputBox("Entrada", "Temperatura (F):", "0")) - 32) * 5 / 9; } float RetornaTempCelsius (void) { return (TempCelsius); } float RetornaTempFahr (void) { return (9 * TempCelsius / 5 + 32); } Temperatura operator ++ (void) { Temperatura x; x.TempCelsius = ++TempCelsius; return x; } Temperatura operator ++ (int) { Temperatura x;

} Temperatura operator -- (void) { Temperatura x; x.TempCelsius = --TempCelsius; return x; } Temperatura operator -- (int) { Temperatura x; --TempCelsius; x.TempCelsius = TempCelsius + 1; return x; } Temperatura operator + (Temperatura x) { x.TempCelsius = TempCelsius + x.TempCelsius; return x; } Temperatura operator - (Temperatura x) { x.TempCelsius = TempCelsius - x.TempCelsius; return x; } Temperatura operator += (Temperatura x) { TempCelsius += x.TempCelsius; return x; } Temperatura operator -= (Temperatura x) { TempCelsius -= x.TempCelsius; return x; } ~Temperatura (void) { } };

x.TempCelsius = TempCelsius++; return x;

Herana entre classes


Pronto! J conhecemos as classes e gora est na hora de tirar vantagem delas. E uma das maiores vantagens da utilizao de classes a herana, que veremos a seguir: Imaginem que a classe Temperatura (feita anteriormente) est pronta e aplicada vrios aplicativos. timo, ela j possui entradas e sadas em C e F. Porm supondo que desejamos sempre aperfeioar nossos aplicativos seria interessante incluir entrada e sada em K (Kelvin), certo? Porm, em processos modularizados (funes), daria muito trabalho e colocaria em risco os aplicativos que por ventura estivessem utilizando esses mdulos. Com uma classe a coisa diferente. Voc pode deixar essa classe intocada e criar uma outra que herde tudo o que existe na antiga. Faremos isso da seguinte forma:

class NeoTemp: public Temperatura { }; A clase nova intitulada de NeoTemp herda todas as propriedades e mtodos da classe temperatura e os torna membros pblicos. Se fosse utilizada a palavra reservada private prescindindo o nome da classe, ento os membros herdados seriam membros privados da classe nova. O nico problema que, por motivos de proteo, os membros private no so passados por herana para outras classes. Ento, em nosso caso, teremos que trabalhar sem a propriedade TempCelsius. Mas isso contornvel e veremos como resolver esse "probleminha" logo adiante. Para implementar os novos mtodos, basta escrev-los:
class NeoTemp: public Temperatura { private: public: void EntraTempKelvin (void) { TempCelsius = StrToFloat(InputBox("Entrada", "Temperatura (C):", "0")) - 273; } float RetornaTempKelvin (void) { return (TempCelsius + 273); }

};

Dessa forma, a classe ainda no funcionar porque a propriedade TempCelsius uma propriedade privada da classe Temperatura e, portanto, no ser reconhecida. Para resolver esse problema, basta acrescentar uma nica linha na classe Temperatura (classe antiga).

Funes e classes friend


Se quisermos que uma classe (ou mesmo funco) tenha acesso s declaraes privadas de nossa classe, podemos fazer isso simplesmente copiando uma declarao da funo ou classe em nossa classe. Em nosso caso, precisamos dizer que a classe nova (NeoTemp) uma classe amiga da classe Temperatura. Reparem que a declarao deve estar dentro da classe Temperatura: class Temperatura { private: float TempCelsius; public: friend class NeoTemp; . .

. }; Pronto! Agora os membros privados tambm sero herdados pela classe NeoTemp e ela funcionar corretamente em nosso programa novo. Se pegarmos o programa antigo e trocar o tipo de objeto de Temperatura para NeoTemp na declarao do objeto: NeoTemp Obj; Veremos que todo o resto continua a funcionar, menos os operadores. E por qu? Porque os mtodos dos operadores possuem argumentos e retornos e, quando o nosso novo objeto utilizado com um determinado operador, a funo no ser chamada porque aqueles argumentos no lhe cabem. Por exemplo: Quando Tentamos o seguinte: NeoTemp Obj2; Obj2.EntraTempCelsius(); Obj = Obj + Obj2; O compilador acusar um erro porque o mtodo herdado pela classe retorna um objeto do tipo Temperatura: Temperatura operator + (Temperatura x) { x.TempCelsius = TempCelsius + x.TempCelsius; return x; } Porm, no programa, o objeto que receber o valor da soma do tipo NeoTemp. A mesma coisa acontece com o argumento do mtodo e por isso, o mtodo soma no chamado. Como no existe nenhum mtodo com essas caractersticas, gera-se um erro de compilao, para resolver esse problema basta sobrecarregar novamente os operadores. Percebemos ento que os operadores so mtodos muito ntimos da classe e, por isso, sempre devem ser sobrecarregados. A classe ficar ento da seguinte forma:
class NeoTemp: public Temperatura { public: void EntraTempKelvin (void) { TempCelsius = StrToFloat(InputBox("Entrada", "Temperatura (C):", "0")) - 273; } float RetornaTempKelvin (void) { return (TempCelsius + 273); } float operator = (float x) {

} NeoTemp operator + (NeoTemp x) { x.TempCelsius = TempCelsius + x.TempCelsius; return x; } NeoTemp operator - (NeoTemp x) { x.TempCelsius = TempCelsius - x.TempCelsius; return x; } NeoTemp operator += (NeoTemp x) { TempCelsius += x.TempCelsius; return x; } NeoTemp operator -= (NeoTemp x) { TempCelsius -= x.TempCelsius; return x; } };

TempCelsius = x; return x;

E pronto!!! A nova classe j est preparada para trabalhar com o programa novo. Existe ainda mais uma sobrecarga de operadores, o de atribuio (=). Dessa forma possvel simplesmente atribuir um valor float ao objeto: Neo Temp Obj; Obj = 10;

Das könnte Ihnen auch gefallen