24
L U I S F E R N A N D O E S P I N O S A C O C I A N 116 5 5 . . P P r r o o g g r r a a m m a a ç ç ã ã o o O O r r i i e e n n t t a a d d a a a a O O b b j j e e t t o o s s e e m m C C + + + + Nesta seção não se pretente mostrar a teoria completa da POO mas tão somente apresentar os conceitos necessários para uma correta programação usando o C++Builder. A POO é um paradigma de programação que se fundamenta nos conceitos de objeto e de classe. Começaremos definindo esses dois conceitos. Objeto: é uma entidade autônoma com uma funcionalidade concreta e bem definida. Classe: é uma especificação das características de um conjunto de objetos. Diz-se que um objeto é uma instância de uma classe. Os conceitos apresentados nesta seção serão ilustrados usando um exemplo que será completado aos poucos à medida que forem introduzidos novos conceitos. Este mesmo exemplo será usado mais adiante nas seções dedicadas ao tratamento de exceções e ã programação com threads. 1. Para iniciar, comece criando um novo projeto usando File + New Application. Salve a aplicação em uma nova pasta nomeando Unit1.cpp para Uprincipal.cpp e Project1.bpr para POOEx.bpr 2. Alterar o nome do quadro (Name = FrmPrincipal). Colocar nele um objeto PaintBox (aba System) com Name = PaintBox, Align = alTop. Deixar um espaço embaixo do PaintBox para colocar um botão. 3. Colocar um objeto Bevel de altura 4 e alinhado por cima (Align = alTop). A idéia é delimitar a parte inferior do objeto PaintBox.

5. Programação Orientada a Objetos em C++epdiieeulbra.synthasite.com/resources/05-POO-C++BuilderV10.pdfL U I S F E R N A N D O E S P I N O S A C O C I A N 116 5. Programação Orientada

  • Upload
    vominh

  • View
    216

  • Download
    1

Embed Size (px)

Citation preview

Page 1: 5. Programação Orientada a Objetos em C++epdiieeulbra.synthasite.com/resources/05-POO-C++BuilderV10.pdfL U I S F E R N A N D O E S P I N O S A C O C I A N 116 5. Programação Orientada

L U I S F E R N A N D O E S P I N O S A C O C I A N

116

55.. PPrrooggrraammaaççããoo OOrriieennttaaddaa aa

OObbjjeettooss eemm CC++++ Nesta seção não se pretente mostrar a teoria completa da POO mas tão

somente apresentar os conceitos necessários para uma correta programação

usando o C++Builder.

A POO é um paradigma de programação que se fundamenta nos conceitos

de objeto e de classe. Começaremos definindo esses dois conceitos.

Objeto: é uma entidade autônoma com uma funcionalidade concreta e

bem definida.

Classe: é uma especificação das características de um conjunto de objetos.

Diz-se que um objeto é uma instância de uma classe.

Os conceitos apresentados nesta seção serão ilustrados usando um

exemplo que será completado aos poucos à medida que forem introduzidos novos

conceitos. Este mesmo exemplo será usado mais adiante nas seções dedicadas

ao tratamento de exceções e ã programação com threads.

1. Para iniciar, comece criando um novo projeto usando File + New Application. Salve a aplicação em uma nova pasta nomeando Unit1.cpp para Uprincipal.cpp e Project1.bpr para POOEx.bpr

2. Alterar o nome do quadro (Name = FrmPrincipal). Colocar nele um objeto PaintBox (aba System) com Name = PaintBox, Align = alTop. Deixar um espaço embaixo do PaintBox para colocar um botão.

3. Colocar um objeto Bevel de altura 4 e alinhado por cima (Align = alTop). A idéia é delimitar a parte inferior do objeto PaintBox.

Page 2: 5. Programação Orientada a Objetos em C++epdiieeulbra.synthasite.com/resources/05-POO-C++BuilderV10.pdfL U I S F E R N A N D O E S P I N O S A C O C I A N 116 5. Programação Orientada

E N G E N H A R I A D E P R O C E S S A M E N T O D I G I T A L I I

117

4. Colocar um objeto BitBtn que permita terminar a execução do programa. O botão deverá estar centralizado horizontalmente na parte inferior do quadro.

5. Criar uma nova unidade cpp usando a opção de menu File + New + Unit. Salvar com o nome ObjGraf.cpp.

6. Quando se cria uma unidade cpp desta forma se crian em verdade dois arquivos, um com extensão .cpp e outro com extensão .h. Assim dispomos dos arquivos ObjGraf.h que conterá as declarações das classes com as que vamos trabalhar e ObjGraf.cpp que conterá as definições (implementações dos métodos) das mesmas.

7. Abra o arquivo ObjGraf.h. Para isto, no Editor de Códigos, clique com o botão direito do mouse acima do arquivo ObjGraf.cpp chamando o menu de contexto e escolha a opção Open Source/Header File CTRL+F6.

Page 3: 5. Programação Orientada a Objetos em C++epdiieeulbra.synthasite.com/resources/05-POO-C++BuilderV10.pdfL U I S F E R N A N D O E S P I N O S A C O C I A N 116 5. Programação Orientada

L U I S F E R N A N D O E S P I N O S A C O C I A N

118

8. Para criar uma classe, colocar o seguinte código em ObjGraf.h. Notar que o nome da classe vai precedido por uma letra T, e embora isto não seja obrigatório, é recomendável o seu uso já que é uma convenção no C++Builder. Você pode usar também outras convenções próprias, como por exemplo, começar com a letra C: CObjGraf. No exemplo a continuação é definida uma classe mas não se criou nenhum objeto ainda.

//-------------------------------------------------- #ifndef ObjGrafH #define ObjGrafH // Definição da classe TObjGraf class TObjGraf {}; #endif //--------------------------------------------------

55..11.. OO PPaarraaddiiggmmaa ddaa PPOOOO eemm CC++++ Existem quatro princípios básicos que qualquer sistema orientado a

objetos tem de incorporar, e que são esquematizados na Figura 5-1.

Encapsulamento

Abstração

Polimorfismo

Herança

POO

Figura 5-1 – Pilares da POO.

55..22.. CCrriiaaççããoo ee DDeessttrruuiiççããoo ddee OObbjjeettooss Já foi dito que uma classe é nada mais (e nada menos) que uma

especificação. Para poder usar a funcionalidade contida na mesma devem se

instanciar as classes.

A criação de objetos de uma classe pode ser feita por declaração explícita

ou por criação dinâmica.

Page 4: 5. Programação Orientada a Objetos em C++epdiieeulbra.synthasite.com/resources/05-POO-C++BuilderV10.pdfL U I S F E R N A N D O E S P I N O S A C O C I A N 116 5. Programação Orientada

E N G E N H A R I A D E P R O C E S S A M E N T O D I G I T A L I I

119

9. Um objeto pode ser instanciado de forma simples, declarando uma variável do tipo da classe. Por exemplo, no arquivo Uprincipal.cpp crie um gerenciador de eventos para o OnCreate (aba Events) e coloque na função criada o seguinte código:

//--------------------------------------------------------------------------- void __fastcall TFrmPrincipal::FormCreate(TObject *Sender) { TObjGraf ObjGraf1(); TObjGraf ObjGraf2; } //---------------------------------------------------------------------------

10. Em Uprincipal.cpp acrescentar o arquivo de cabeçalho ObjGraf usando a opção de menu File + Include Unit Hdr.

No programa serão criados dois objetos de forma, ObjGraf1 e ObjeGraf2

que são da classe TObjGraf. Esta forma de instanciação é bastante usada na

programação clássica usando C++, no entanto no C++ Builder é utilizada em

raras ocasiões. Isto é por duas razões fundamentais:

� A duração dos objetos costuma ir além de uma simples função ou bloco. Devido ao enfoque de programação orientada à eventos, é comum que um objeto seja criado dentro de um gerenciadorde eventos e seja destruido em outro.

� Não é possível esta modalidade de criação com os objetos da VCL.

Uma outra forma de criar objetos mais apropriada no C++Builder é a

criação dinâmica, realizada mediante o uso do operador new.

Quando é usado o operador new para instanciar um novo objeto deve se

usar uma variável que referencie ou aponte para o novo objeto criado (de outra

forma esse ficaria totalmente inacessível). Assim, se requer de uma declaração

prévia de um ponteiro para objetos do tipo da classe que vai se criar.

Para instanciar um objeto de forma dinâmica alterar o código da unidade

Uprincipal.cpp para parecer como segue:

TObjGraf * ObjGraf; // Variável Global dentro da unidade .cpp. // ObjGraf é um ponteiro para objetos do tipo TObjGraf //-------------------------------------------------- void __fastcall TFrmPrincipal::FormCreate(TObject *Sender){ ObjGraf = new TObjGraf; } //--------------------------------------------------

Page 5: 5. Programação Orientada a Objetos em C++epdiieeulbra.synthasite.com/resources/05-POO-C++BuilderV10.pdfL U I S F E R N A N D O E S P I N O S A C O C I A N 116 5. Programação Orientada

L U I S F E R N A N D O E S P I N O S A C O C I A N

120

A forma de estabelecer o estado inicial ou de destruir os componentes de

um objetos serão estudados mais adiante na seção Construtores e Destrutores.

Quando se utiliza esta forma de instanciação de classes é de

responsabilidade do programador a correta destruição dos objetos criados.

Quando um objeto deixa de ser útil deve ser eliminado. Assim a aplicação

recupera os recursos (memória) que o objeto tinha ocupado quando foi criado. A

destruição dos objetos criados em tempo de execução com new é feita mediante o

operador delete.

No exemplo, crie um gerenciador de eventos do quadro para o evento

OnDestroy (aba Events do Inspetor de Objetos) e escreva o código que segue em

UPrincipal.cpp:

//--------------------------------------------------------------------------- void __fastcall TFrmPrincipal::FormDestroy(TObject *Sender) { delete ObjGraf; } //---------------------------------------------------------------------------

55..33.. EEnnccaappssuullaammeennttoo Na programação clássica (linguagem C por exemplo) existem dados e

procedimenos que atuam com esses dados. Não há uma relação aparente entre

dados e procedimentos (funções) e esta relação se estabelece de forma mais ou

menos precisa de acordo com a habilidade do programador.

Em um objeto pode se distinguir dois aspectos bem diferenciados:

� Estado: que são as propriedades do objeto

� Comportamento: que são os métodos (funções) que o objeto pode executar.

Na POO os dados e os procedimentos processam esses dados esstão

relacionados explicitamente e se “encapsulam” dentro do objeto. A especificação

das propriedades de um objeto e os métodos de acesso se realiza na declaração

da classe da qual o objeto foi instanciado. A Figura 5-2 esquematiza as

propriedades e os métodos que serão associados aos objetos da classe TObjGraf.

Page 6: 5. Programação Orientada a Objetos em C++epdiieeulbra.synthasite.com/resources/05-POO-C++BuilderV10.pdfL U I S F E R N A N D O E S P I N O S A C O C I A N 116 5. Programação Orientada

E N G E N H A R I A D E P R O C E S S A M E N T O D I G I T A L I I

121

TObjGraf

Mostrar() Coordenada x

Coordenada y

Cor

PaintBox

Classe TObjGraf

unsigned int unX = 0

unsigned int unY = 0

TColor Cor = clBlue

TPaintBox PaintBox

void Mostrar (void)

Figura 5-2 – Propriedades e métodos da classe TObjGraf e a sua representação em UML9.

A declaração das propriedades e métodos dos objetos da classe TObjGraf

será realizada da seguinte maneira (em ObjGraf.h):

//--------------------------------------------------------------------------- class TObjGraf { public: unsigned int unX; // Propriedades unsigned int unY; TColor Cor; TPaintBox *PaintBox; void Mostrar (void); // Métodos }; //---------------------------------------------------------------------------

Observar no Explorador de Classes a classe TObjGraf e os seus

componentes (métodos e propriedades).

55..33..11.. AAcceessssoo aaooss MMeemmbbrrooss ddee uumm OObbjjeettoo Para poder acessar os membros de um objeto se usam os operadores

típicos de acesso a membros: o operador ponto (.) para referenciar diretamente o

9 A UML (Unified Modeling Language) é uma linguagem para especificação, documentação, visualização e desenvolvimento de sistemas orientados a objetos. Sintetiza os principais métodos existentes, sendo considerada uma das linguagens mais expressivas para modelagem de sistemas orientados a objetos. Por meio de seus diagramas é possível representar sistemas de softwares sob diversas perspectivas de visualização. Facilita a comunicação de todas as pessoas envolvidas no processo de desenvolvimento de um sistema - gerentes, coordenadores, analistas, desenvolvedores - por apresentar um vocabulário de fácil entendimento.

Page 7: 5. Programação Orientada a Objetos em C++epdiieeulbra.synthasite.com/resources/05-POO-C++BuilderV10.pdfL U I S F E R N A N D O E S P I N O S A C O C I A N 116 5. Programação Orientada

L U I S F E R N A N D O E S P I N O S A C O C I A N

122

objeto e o operador seta (->) para acesso através de um ponteiro. Os membros

dos objetos criados com o operador new (que são referenciados por ponteiros)

devem ser acessados pelo operador seta (->).

Para observar um exemplo de acesso, alterar a unidade Uprincipal.cpp no

gerenciador do evento OnCreate para parecer como segue:

//--------------------------------------------------------------------------- void __fastcall TFrmPrincipal::FormCreate(TObject *Sender) { ObjGraf = new TObjGraf; int ValorY; ObjGraf->unX = 5; ValorY = ObjGraf->unY; ObjGraf->Mostrar(); //Equivale a (*Obj).Mostrar(); } //---------------------------------------------------------------------------

Este código ainda não poderá ser executado, pois o método TObjGraf-

>Mostrar() ainda não foi definido. De qualquer forma, serve como exemplo de

forma de acesso.

55..44.. CCoonnssttrruuttoorreess ee DDeessttrruuttoorreess Os construtores e destrutores são métodos padronizados que permitem

estabelecer o estado inicial e final de um objeto. Os construtores podem ser

definidos com um conjunto arbitrário de argumentos, mas não podem retornar

valor. Os destrutores são métodos que não podem receber nenhum tipo de

argumento e não podem retornar nenhum valor.

Os construtores devem ter o mesmo nome da classe e o destrutor também

com a diferença de que este último deve vir precedido do caractere til (~).

O construtor é executado quando se cria um novo objeto: 1) por declaração

ou; 2) quando é criado dinamicamente com o operador new.

Um destrutor é executado quando o objeto deixa de existir: 1) porque

acaba o seu âmbito ou; 2) quando é liberado explicitamente da memória com o

operador delete.

Um exemplo de declaração de um construtor e destrutor para o objeto

TObjGraf poderia ser:

Em ObjGraf.h:

class TObjGraf { ... // Construtor de objetos TObjGraf

Page 8: 5. Programação Orientada a Objetos em C++epdiieeulbra.synthasite.com/resources/05-POO-C++BuilderV10.pdfL U I S F E R N A N D O E S P I N O S A C O C I A N 116 5. Programação Orientada

E N G E N H A R I A D E P R O C E S S A M E N T O D I G I T A L I I

123

TObjGraf (TPaintBox *_PaintBox, TColor _Color=clBlack, int _X=0, int _Y=0); // O destrutor poderia ser: ~TObjGraf (void); };

Em ObjGraf.cpp:

//--------------------------------------------------------------------------- TObjGraf::TObjGraf (TPaintBox * _PaintBox, TColor _Cor, int _X, int _Y) { PaintBox = _PaintBox; Cor = _Color; unX = _X; unY = _Y; } //---------------------------------------------------------------------------

Em UPrincipal.cpp:

//--------------------------------------------------------------------------- void __fastcall TFrmPrincipal::FormCreate(TObject *Sender) { ObjGraf = new TObjGraf (PaintBox, clRed, 10, 10); } //---------------------------------------------------------------------------

Em geral não é necessário escrever um destrutor a não ser que o objeto

requeira memória dinâmica adicional. Se for o caso, a tarefa do destrutor será

basicamente liberar a memória dinâmica que ocupa o objeto que vai ser

destruído.

55..55.. HHeerraannççaa Quando uma classe herda de outra, a classe derivada incorpora todos os

membros da classe base além dos membros próprios da mesma. A herança é

uma ferramenta muito importante em muitos aspectos do desenvolvimento de

aplicações:

• Organização do projeto

• Reutilização de classes (próprias ou não)

• Facilita a manutenção do código

Tomando como base a classe TObjGraf construiremos duas novas classes:

TCirculo e TQuadrado, que derivam de TObjGraf. Isto significa que os objetos

dessas classes terão associadas as propriedades e os métodos da classe base

TObjGraf além dos seus próprios. A Figura 5-3 esquematiza o mecanismo de

herança para as novas classes e as novas propriedades que se associam aos

objetos das classes derivadas.

Page 9: 5. Programação Orientada a Objetos em C++epdiieeulbra.synthasite.com/resources/05-POO-C++BuilderV10.pdfL U I S F E R N A N D O E S P I N O S A C O C I A N 116 5. Programação Orientada

L U I S F E R N A N D O E S P I N O S A C O C I A N

124

TObjGraf

Mostrar() Coordenada x

Coordenada y

Cor

TCirculo

Raio

TQuadrado

Lado

Figura 5-3 - As classes TCirculo e TQuadrado herdam as propriedades e métodos da classe TObjGraf.

Para ilustrar o exemplo, alterar as unidades como segue:

Em ObjGraf.h:

//--------------------------------------------------------------------------- // Definição da classe derivada TCirculo // Deriva da classe base TObjGraf class TCirculo : public TObjGraf { public: unsigned int unRadio; // Propriedade exclusiva de TCirculo }; //--------------------------------------------------------------------------- // Definição da classe derivada TQuadrado. // Deriva da classe base TObjGraf class TCuadrado : public TObjGraf { public: unsigned int unLado; // Propriedade exclusiva de TQuadrado }; //---------------------------------------------------------------------------

Antes do nome da classe base foi colocado o especificador de acesso public

que define a forma em que os membros da clase base poderão ser acessados (ou

não:

Derivação public: os membros public da classe base são public na classe

derivada; os membros protected permanecem protected e; os membros private

permanecem private.

Derivação protected: os membros public e protected da classe base são

protected na classe derivada; os membros private permanecem private.

Derivação private: os membros public e protected da classe base são

private na classe derivada; os membros private permanecem private.

55..55..11.. HHeerraannççaa ddee CCoonnssttrruuttoorreess ee

DDeessttrruuttoorreess Os construtores e destrutores de uma classe não são herdados

automaticamente pelas classes derivadas. Construtores e destrutores próprios

devem ser criados nas classes derivadas. No entanto, é possível utilizar os

Page 10: 5. Programação Orientada a Objetos em C++epdiieeulbra.synthasite.com/resources/05-POO-C++BuilderV10.pdfL U I S F E R N A N D O E S P I N O S A C O C I A N 116 5. Programação Orientada

E N G E N H A R I A D E P R O C E S S A M E N T O D I G I T A L I I

125

construtores da classe base porém isto deve ser indicado explicitamente. Assim,

é útil saber que o construtor da classe base é invocado automaticamente antes

que o construtor da classe derivada e que o destrutor da classe derivada se

invoca antes que o da classe base. Para determinar com quais parâmetros se

chamará o construtor da classe base, se utiliza uma lista de Inicialização. Para

ilustrar no exemplo, alterar o código como segue:

Em ObjGraf.h:

//--------------------------------------------------------------------------- // Definição da classe derivada TCirculo // Deriva da classe base TObjGraf class TCirculo : public TObjGraf { public: unsigned int unRadio; // Propriedade exclusiva de TCirculo // Método construtor TCirculo (TPaintBox *_PaintBox, TColor _Color=clBlue, int _X=0, int _Y=0, int _Radio=1); }; //--------------------------------------------------------------------------- // Definição da classe derivada TQuadrado. // Deriva da classe base TObjGraf class TCuadrado : public TObjGraf { public: unsigned int unLado; // Propriedade exclusiva de TQuadrado // Método construtor TQuadrado (TPaintBox * _PaintBox, TColor _Color=clBlue, int _X=0, int _Y=0, int _Lado=1); }; //---------------------------------------------------------------------------

Em ObjGraf.cpp:

//--------------------------------------------------------------------------- TCirculo::TCirculo (TPaintBox * _PaintBox, TColor _Color, int _X, int _Y, int _Radio) : TObjGraf (_PaintBox, _Color, _X, _Y) { unRaio = _Radio; } //--------------------------------------------------------------------------- TQuadrado::TQuadrado (TPaintBox * _PaintBox, TColor _Color, int _X, int _Y, int _Lado) : TObjGraf (_PaintBox, _Color, _X, _Y) { unLado = _Lado; } //---------------------------------------------------------------------------

55..55..22.. CCllaasssseess AAbbssttrraattaass Uma classe abstrata é uma classe que não está completamente

especificada (que possui métodos sem implementar), e portanto não se podem

criar instâncias de si mesmas. Uma classe abstrata se usa para servir de classe

base a outras classes. Na terminologia C++ diz-se que uma classe abstrata é

Page 11: 5. Programação Orientada a Objetos em C++epdiieeulbra.synthasite.com/resources/05-POO-C++BuilderV10.pdfL U I S F E R N A N D O E S P I N O S A C O C I A N 116 5. Programação Orientada

L U I S F E R N A N D O E S P I N O S A C O C I A N

126

aquela que possui pelo menos um método virtual puro. Os métodos virtuais

obrigam às classes derivadas a implementar esse método. O termo puro significa

que não podem ser criadas instâncias diretamente desta classe (somente

derivadas).

Para visualizar esta funcionalidade, alterar o código do exemplo como

segue:

Em ObjGraf.h:

//--------------------------------------------------------------------------- class TObjGraf { public: … virtual void Mostrar(void) = 0; // Método virtual puro … }; //--------------------------------------------------------------------------- // Definição da classe derivada TCirculo // Deriva da classe base TObjGraf class TCirculo : public TObjGraf { public: … // Instanciação do método virtual puro da clase TObjGraf void Mostrar (void); }; //--------------------------------------------------------------------------- // Definição da classe derivada TQuadrado. // Deriva da classe base TObjGraf class TQuadrado : public TObjGraf { public: … // Instanciação do método virtual puro da clase TObjGraf void Mostrar (void); }; //---------------------------------------------------------------------------

Em ObjGraf.cpp:

//--------------------------------------------------------------------------- void TCirculo::Mostrar(void) { PaintBox->Canvas->Pen->Color = Cor; PaintBox->Canvas->Brush->Color = Cor; PaintBox->Canvas->Ellipse(unX, unY, unX + unRaio * 2, unY + unRaio * 2); } //--------------------------------------------------------------------------- void TQuadrado::Mostrar(void) { PaintBox->Canvas->Pen->Color = Cor; PaintBox->Canvas->Brush->Color = Cor; PaintBox->Canvas->Rectangle(unX, unY, unX + unLado, unY + unLado); } //---------------------------------------------------------------------------

Por que se especifica o método Mostrar() em TObjGraf como virtual puro

no lugar de simplesmente omiti-lo? Fundamentalmente podem ser consideradas

duas razões principais para usar métodos virtualmente puros:

Page 12: 5. Programação Orientada a Objetos em C++epdiieeulbra.synthasite.com/resources/05-POO-C++BuilderV10.pdfL U I S F E R N A N D O E S P I N O S A C O C I A N 116 5. Programação Orientada

E N G E N H A R I A D E P R O C E S S A M E N T O D I G I T A L I I

127

� Para obrigar que as classes derivadas os implementem. Desta forma estamos seguros que todas as classes descendentes não abstratas de TObjGraf possuem o método e que poderão ser invocados com segurança.

� Para evitar que se possam criar instâncias da classe abstrata.

Neste estado, se o programa tentar ser executado aparecerá uma

mensagem de erro:

[C++ Error] UPrincipal.cpp(24): E2352 Cannot create instance of abstract class 'TObjGraf'

Não se pode criar uma instância de uma classe abstrata. Mas por que

acontece este erro? Lembrar que em UPrincipal.cpp o gerenciador associado ao

evento OnCreate do quadro possui a seguinte declaração que deve ser apagada:

//--------------------------------------------------------------------------- void __fastcall TFrmPrincipal::FormCreate(TObject *Sender) { ObjGraf = new TObjGraf (PaintBox, clRed, 10, 10); } //---------------------------------------------------------------------------

Apagar também o código colocado no destrutor:

//--------------------------------------------------------------------------- void __fastcall TFrmPrincipal::FormDestroy(TObject *Sender) { delete ObjGraf; } //---------------------------------------------------------------------------

A continuação criaremos os objetos das classes derivadas. Inicialmente

apagar a declaração da variável global em UPrincipal.cpp:

TObjGraf * ObjGraf; // Variável Global dentro da unidade .cpp. // ObjGraf é um ponteiro para objetos do tipo TObjGraf

No lugar dessa declarar quatro ponteiros, dois para referenciar a objetos

do tipo TCirculo e outros dois para referenciar a objetos do tipo TQuadrado

(ainda em UPrincipal.cpp).

// Ponteiros para objetos das classes derivadas. TCirculo *Cir1, *Cir2; TQuadrado *Quad1, *Quad2;

A continuação modificar a função FormCreate para criar dois objetos de

cada classe referenciados para os ponteiros declarados anteriormente.

//--------------------------------------------------------------------------- void __fastcall TFrmPrincipal::FormCreate(TObject *Sender) { Cir1 = new TCirculo (PaintBox, clBlue, 50, 50, 30); Cir2 = new TCirculo (PaintBox, clRed, 210, 40, 70); Quad1 = new TQuadrado (PaintBox, clGreen, 320, 150, 45); Quad2 = new TQuadrado (PaintBox, clWhite, 190, 30, 40); } //---------------------------------------------------------------------------

Finalmente, modificar a função FormDestroy para eliminar os objetos

criados no fechamento da janela.

//--------------------------------------------------------------------------- void __fastcall TFrmPrincipal::FormDestroy(TObject *Sender)

Page 13: 5. Programação Orientada a Objetos em C++epdiieeulbra.synthasite.com/resources/05-POO-C++BuilderV10.pdfL U I S F E R N A N D O E S P I N O S A C O C I A N 116 5. Programação Orientada

L U I S F E R N A N D O E S P I N O S A C O C I A N

128

{ delete Cir1; delete Cir2; delete Quad1; delete Quad2; } //---------------------------------------------------------------------------

Ao executar o programa se criam e destrói os objetos das classes derivadas

embora não sejam visualizados na janela. Por que? Em nenhum momento foi

chamado o método Mostrar() associado a cada objeto. Para mostrar os objetos

basta com indicarlo no gerenciador associado ao evento OnPain do componente

PaintBox. Adicione a esse gerenciador o seguinte código:

//--------------------------------------------------------------------------- void __fastcall TFrmPrincipal::PaintBoxPaint(TObject *Sender) { Cir1->Mostrar(); Cir2->Mostrar(); Quad1->Mostrar(); Quad2->Mostrar(); } //---------------------------------------------------------------------------

Neste ponto o projeto ao ser executado deverá aparecer da seguinte forma:

EEXXEERRCCÍÍCCIIOO AADDIICCIIOONNAALL Construir a classe TTriangulo e modificar o projeto para que proporcione

um resultado similar ao da Figura 5-4.

Page 14: 5. Programação Orientada a Objetos em C++epdiieeulbra.synthasite.com/resources/05-POO-C++BuilderV10.pdfL U I S F E R N A N D O E S P I N O S A C O C I A N 116 5. Programação Orientada

E N G E N H A R I A D E P R O C E S S A M E N T O D I G I T A L I I

129

Figura 5-4 - Resultado do proyecto POOEx.bpr mostrando objetos da classe TTriangulo.

55..55..33.. HHeerraannççaa MMúúllttiippllee A herança múltiple é o fato de que uma classe derivada seja gerada a

partir de várias classes base. Para entender melhor o fato, considerar que em

uma aplicação para uma concessionária de automóveis pode existir a seguinte

hierarquia de classes:

class TProduto { unsigned int unPreco; ... }; class TVeiculo { unsignede int NumRodas; ... }; class TAutoEmVenda : public TProduto, public TVeiculo { ... };

Observar que os objetos da classe TAutoEmVenda derivam das classes

TProduto e TVeiculo. Existem duas formas para que uma classe tire vantagem de

outra, uma é a herança e outra é que a classe contenha um objeto da outra

classe. Nenhuma das duas possibilidades pode ser considerada melhor que a

outra, em cada caso em particular terá que se estudar qual a melhor opção.

Por exemplo, se desejarmos criar uma classe TMoldura que representa a

moldura de um quadro que pssa representar tanto um quadrado quanto um

círculo, pode se decidir por diferentes estratégias na hora de implementar a

classe:

� Herdar de TCirculo e TQuadrado.

� Herdar de TObjGraf e conter um objeto do tipo TCirculo e um outro do tipo TQuadrado.

� Herdar de TCirculo e que contenha um objeto da classe TQuadrado.

Page 15: 5. Programação Orientada a Objetos em C++epdiieeulbra.synthasite.com/resources/05-POO-C++BuilderV10.pdfL U I S F E R N A N D O E S P I N O S A C O C I A N 116 5. Programação Orientada

L U I S F E R N A N D O E S P I N O S A C O C I A N

130

� Herdar de TQuadrado e que contenha um objeto da classe TCirculo.

55..66.. AAbbssttrraaççããoo Abstração é o ocultamento de detalhes irrelevantes que não se desejam

mostrar. Pode se distingüir em uma classe dois aspectos do ponto de vista da

abstração:

� Interface: é o que se pode visualizar e usar de um objeto.

� Implementação: é como se leva a cabo a sua funcionalidade.

Resumindo, nos interessa saber o que nos oferece um objeto, e não como

ele faz isto acontecer.

55..66..11.. RReessttrriiççõõeess ddee aacceessssoo eemm CC++++ Na linguagem C++ pode se especificar o acesso aos membros de uma

classe usando os seguintes especificadores de acesso:

� public: interface da classe.

� private: implementação da classe.

� protected: implementação da familia.

Esses especificadores não modificam a forma de acesso e nem o

comportamento, no entanto controlam desde onde se podem usar os membros da

classe.

� public: desde qualquer lugar.

� private: desde os métodos da classe.

� protected: desde os métodos da clase e desde os métodos das classes derivadas.

Para ilustrar, alterar as seguintes linhas no projeto POOEx.bpr:

Em ObjGraf.h:

//--------------------------------------------------------------------------- class TObjGraf { private: unsigned int unX; // Propriedades unsigned int unY; protected: TColor Cor; TPaintBox *PaintBox; public: virtual void Mostrar(void) = 0; // Método virtual puro // Construtor de objetos TObjGraf TObjGraf (TPaintBox *_PaintBox, TColor _Cor=clBlue, int _X=0, int _Y=0); // O destrutor seria: ~TObjGraf (void); }; //---------------------------------------------------------------------------

Page 16: 5. Programação Orientada a Objetos em C++epdiieeulbra.synthasite.com/resources/05-POO-C++BuilderV10.pdfL U I S F E R N A N D O E S P I N O S A C O C I A N 116 5. Programação Orientada

E N G E N H A R I A D E P R O C E S S A M E N T O D I G I T A L I I

131

Da mesma forma, alterar as classes TCirculo e TQuadrado para que as

suas propriedades unRaio e unLado fiquem protegidas e os seus métodos ainda

fiquem públicos.

//--------------------------------------------------------------------------- // Definição da classe derivada TCirculo // Deriva da classe base TObjGraf class TCirculo : public TObjGraf { protected: unsigned int unRaio; // Propriedade exclusiva de TCirculo public: // Método construtor TCirculo (TPaintBox *_PaintBox, TColor _Color=clBlue, int _X=0, int _Y=0, int _Radio=1); // Instanciação do método virtual puro da clase TObjGraf void Mostrar (void); }; //--------------------------------------------------------------------------- // Definição da classe derivada TQuadrado. // Deriva da classe base TObjGraf class TQuadrado : public TObjGraf { protected: unsigned int unLado; // Propriedade exclusiva de TQuadrado public: // Método construtor TQuadrado (TPaintBox * _PaintBox, TColor _Color=clBlue, int _X=0, int _Y=0, int _Lado=1); // Instanciação do método virtual puro da clase TObjGraf void Mostrar (void); }; //---------------------------------------------------------------------------

Se em UPrincipal.cpp formos escrever:

//--------------------------------------------------------------------------- void __fastcall TFrmPrincipal::FormCreate(TObject *Sender) {

… Cir1->Mostrar(); // pode … Cir1->unX = 10; // Não pode porque unX é private. } //---------------------------------------------------------------------------

Aqui acontecerá o seguinte erro:

[C++ Error] UPrincipal.cpp(34): E2247 'TObjGraf::unX' is not accessible

Os três especificadores de acesso são próprios da linguagem C++, no

entanto o C++Builder possui um outro especificador adicional denominado

__published. Não vai se dar muita importância a este especificador porque o seu

uso está restrito ao IDE. Quando em uma classe vejamos uma seção __published

que dizer que os membros contidos na mesma são mantidos automaticamente

pelo IDE e não devemos modificar nada nesta seção sob pena de obter resultados

imprevisíveis.

Page 17: 5. Programação Orientada a Objetos em C++epdiieeulbra.synthasite.com/resources/05-POO-C++BuilderV10.pdfL U I S F E R N A N D O E S P I N O S A C O C I A N 116 5. Programação Orientada

L U I S F E R N A N D O E S P I N O S A C O C I A N

132

É uma boa prática de programação não permitir o acesso público às

propriedades de um objeto, já que isto pode colocar em perigo a sua integridade.

Então, como se pode alterar o estado de um objeto desde o exterior?

� Oferecendo métodos (públicos) que se encarregem de modificar as propriedades (privadas). Desta maneira são os métodos que acessam às propriedades e o usuário da classe somente tem acesso através deles. Esta é a técnica clássica que se utiliza em C++.

� Através dos métodos e propriedades “virtuais”. Esta técnica é exclusiva do C++Builder e será descrita na próxima seção.

55..66..22.. PPrroopprriieeddaaddeess VViirrttuuaaiiss São propriedades definidas mediante métodos de leitura (read) e/ou

escrita (write). Chama-se virtuais porque realmente não existem. O usuário da

classe usa estas propriedades como se fossem propriedades reais e em última

instância se traduzem na chamada a um método ou no acesso da propriedade

real. Mais ainda, se uma propriedade virtual é usada para leitura (por exemplo

na parte direita de uma atribuição) se traduz em uma ação diferente que se essa

propriedade virtual é usada para a escrita.

A ação se produz quando a propriedade virtual é de leitura, especificada

sintaticamente mediante a palavra reservada read, enquanto que se for usada

para escrita se especifica com write. Veja a alteração no projeto de exemplo, para

ilustrar o uso de propriedades virtuais.

Em ObjGraf.h:

//--------------------------------------------------------------------------- class TObjGraf { private:

unsigned int unFX; // foram alterados os nomes unsigned int unFY; // de unX para unFX e unY para unFY

void SetX(int _X); void SetY(int _Y);

virtual int GetLargura (void) = 0; // Método virtual puro virtual int GetAltura (void) = 0; // Método virtual puro protected: TColor FCor; // mudou de Cor para FCor TPaintBox *PaintBox; public: virtual void Mostrar(void) = 0; // Método virtual puro // Construtor de objetos TObjGraf TObjGraf (TPaintBox *_PaintBox, TColor _Cor=clBlue, int _X=0, int _Y=0); // O destrutor seria: ~TObjGraf (void); // Novas Formas de Acesso com propriedades virtuais. __property unsigned int unX = {read=unFX, write=SetX}; __property unsigned int unY = {read=unFY, write=SetY};

Page 18: 5. Programação Orientada a Objetos em C++epdiieeulbra.synthasite.com/resources/05-POO-C++BuilderV10.pdfL U I S F E R N A N D O E S P I N O S A C O C I A N 116 5. Programação Orientada

E N G E N H A R I A D E P R O C E S S A M E N T O D I G I T A L I I

133

__property TColor Cor = {read=FCor, write=FCor}; __property unsigned int unLargo = {read=GetLargura }; __property unsigned int unAlto = {read=GetAltura }; }; //---------------------------------------------------------------------------

Observar que a antiga propriedade unX (e unY) teve o nome alterado para

unFX (e unFY). Além disso há uma propriedade virtual (pública) chamada unX (e

unY). Essas propriedades estão declaradas na classe TObjGraf o que significa

que as suas descendentes também a herdarão.

Se em UPrincipal.cpp se usasse uma propriedade para leitura:

int CX = Cir1->unX;

é a mesma coisa que:

int CX = Cir1->unFX;

já que quando se acessa para letura a propriedade virtual unX na

realidade se acessa a propriedade real unFX. A última instrução, no entanto,

provocaria um erro porque a propriedade unFX foi declarada como privada.

Se a propriedade em questão for usada para escrita:

Cir1->X = 100;

Na realidade é como se fizesse:

Cir1->SetX(100);

Já que quando se acessa para escrita a propriedade virtual unX, na

realidade se chama o método SetX(); A última instrução, entretanto, provocaria

um erro pois SetX() é um método privado. Ao redirecionar a escrita para o

método SetX() pode se controlar a validade do parâmetro e corrigir, se for o caso,

o valor, o que proporciona uma vantagem adicional.

A propriedade virtual Cor possui o mesmo método associado tanto para

leitura quanto para escrita: retorna o que escreve, diretamente na propriedade

real FCor.

Finalmente, observar que as propriedades virtuais unLargo e unAlto não

possuem métodos de acesso para escrita. Por esses dois métodos terem sido

declarados virtuais puros precisa-se instanciá-los nas classes derivadas.

Ainda em ObjGraf.h:

//--------------------------------------------------------------------------- // Definição da classe derivada TCirculo // Deriva da classe base TObjGraf class TCirculo : public TObjGraf { protected: unsigned int unRaio; // Propriedade exclusiva de TCirculo inline int GetLargura (void) {return(unRaio*2);} inline int GetAltura (void) {return(unRaio*2);}

Page 19: 5. Programação Orientada a Objetos em C++epdiieeulbra.synthasite.com/resources/05-POO-C++BuilderV10.pdfL U I S F E R N A N D O E S P I N O S A C O C I A N 116 5. Programação Orientada

L U I S F E R N A N D O E S P I N O S A C O C I A N

134

public: // Método construtor TCirculo (TPaintBox *_PaintBox, TColor _Color=clBlue, int _X=0, int _Y=0, int _Radio=1); // Instanciação do método virtual puro da clase TObjGraf void Mostrar (void); }; //--------------------------------------------------------------------------- // Definição da classe derivada TQuadrado. // Deriva da classe base TObjGraf class TQuadrado : public TObjGraf { protected: unsigned int unLado; // Propriedade exclusiva de TQuadrado inline int GetLargura (void) {return(unLado);} inline int GetAltura (void) {return(unLado);} public: // Método construtor TQuadrado (TPaintBox * _PaintBox, TColor _Color=clBlue, int _X=0, int _Y=0, int _Lado=1); // Instanciação do método virtual puro da clase TObjGraf void Mostrar (void); }; //---------------------------------------------------------------------------

Agora, adicionar em ObjGraf.cpp as funções write das propriedades

virtuais unX e unY:

//--------------------------------------------------------------------------- // Funções de escrita das propriedades virtuais unX e unY void TObjGraf::SetX(unsigned int _X) { if (_X < 0) // Coordenada negativa unFX = 0; // Ajustar para a margem esquerda else if (_X > (PaintBox->Width - unLargo)) // Alta demais unFX = PaintBox->Width - unLargo; // Ajustar para a margem direita else unFX = _X; // Correto: escrever sem modificar } //--------------------------------------------------------------------------- void TObjGraf::SetY(unsigned int _Y) { if (_Y < 0) // Coordenada negativa unFY = 0; // Ajustar a margem superior else if (_Y > (PaintBox->Height - unAlto)) // alto demais unFY = PaintBox->Height - unAlto; // Ajustar para a margem inferior else unFY = _Y; // Correto: escrever sem modificar } //---------------------------------------------------------------------------

É importante notar que foi alterado o construtor da classe TObjGraf

porque não se pode chamar os métodos virtuais puros de uma propriedade

virtual desde um construtor de uma classe base. Neste caso, não se pode chamar

os métodos virtuais puros (GetLargura() e GetAltura()) das propriedades virtuais

(unLargo e unAlto) desde o construtor da classe base TObjGraf.

Em ObjGraf.cpp:

Page 20: 5. Programação Orientada a Objetos em C++epdiieeulbra.synthasite.com/resources/05-POO-C++BuilderV10.pdfL U I S F E R N A N D O E S P I N O S A C O C I A N 116 5. Programação Orientada

E N G E N H A R I A D E P R O C E S S A M E N T O D I G I T A L I I

135

//--------------------------------------------------------------------------- TObjGraf::TObjGraf (TPaintBox * _PaintBox, TColor _Color, int _X, int _Y) { PaintBox = _PaintBox; FCor = _Color; unFX = _X; unFY = _Y; } //---------------------------------------------------------------------------

Neste ponto o projeto deve estar funcionando como antigamente.

55..77.. PPoolliimmoorrffiissmmoo O Polimorfismo é o fato de demonstrar comportamentos distintos segundo

a situação. Pode se dar de três formas diferentes:

� Funções: sobrecarga.

� Classes: é ao que se refere normalmente o conceito de polimorfismo.

� Enlace dinámico: métodos virtuais.

55..77..11.. SSoobbrreeccaarrggaa ddee ffuunnççõõeess Ocorre quando em uma classe existem dois ou mais métodos com o

mesmo nome mas com distintas listas de parâmetros. O compilador os considera

como métodos distintos e aplica cada um deles na situação apropriada. Por

exemplo, pode se sobrecarregar o construtor da classe TObjGraf adicionando um

novo construtor de cópia:

Em ObjGraf.h:

class TObjGraf { …

public: … // Construtor de objetos TObjGraf TObjGraf (TPaintBox *_PaintBox, TColor _Cor=clBlue, int _X=0, int _Y=0);

TObjGraf (TObjGraf *ObjGraf); // sobrecarga de construtor … };

Em ObjGraf.cpp:

//--------------------------------------------------------------------------- TObjGraf::TObjGraf (TPaintBox * _PaintBox, TColor _Color, int _X, int _Y) { PaintBox = _PaintBox; FCor = _Color; unFX = _X; unFY = _Y; } //--------------------------------------------------------------------------- TObjGraf::TObjGraf (TObjGraf *ObjGraf) {

Page 21: 5. Programação Orientada a Objetos em C++epdiieeulbra.synthasite.com/resources/05-POO-C++BuilderV10.pdfL U I S F E R N A N D O E S P I N O S A C O C I A N 116 5. Programação Orientada

L U I S F E R N A N D O E S P I N O S A C O C I A N

136

PaintBox = ObjGraf->PaintBox; FCor = ObjGraf->Cor; unFX = ObjGraf->unFX; unFY = ObjGraf->unFY; } //---------------------------------------------------------------------------

55..77..22.. PPoolliimmoorrffiissmmoo nnaass ccllaasssseess ee

mmééttooddooss vviirrttuuaaiiss Uma classe pode se comportar como qualquer das suas antecessoras (por

exemplo, na atribuição). Como há variáveis (ponteiros) que podem conter objetos

de distintas classes, o compilador não sabe qual tipo de objeto é o realmente

apontado pelo ponteiro (em tempo de compilação) por tanto esta definição deve

ser deixada para o tempo de execução. O enlace dinâmico é atrasar o enlace de

uma chamada a um método (função) em tempo de execução.

Para ilustrar o polimorfismo criaremos uma nova classe TBola que deriva

de TCirculo. Uma bola (objeto do tipo TBola para ser mais preciso) é um círculo

que possui a capacidade de movimento. Para implementar o movimento de uma

bola precisamos incorporar novas propriedades e métodos próprios à classe

TBola. No entanto, neste momento nos interessa colocar de manifesto o

polimorfismo, fato que pode ser conseguido através do método Mostrar()

associado à classe TBola. Antes, modificaremos a declaração do método Mostrar()

da classe TCirculo para obrigar a suas descendentes a implementar o seu próprio

método Mostrar(). Para isto basta indicar que o método Mostrar() da classe

TCirculo é virtual.

Em ObjGraf.h:

//--------------------------------------------------------------------------- // Definição da classe derivada TCirculo // Deriva da classe base TObjGraf class TCirculo : public TObjGraf {

… public:

… // Instanciação do método virtual puro da clase TObjGraf // Agora o método Mostrar() é declarado virtual, embora não seja puro: // 1) Por ser virtual: qualquier classe que derive de TCirculo deve // ter o seu própiro método Mostrar(), // 2) Por não ser puro: pode se chamar este método com objetos TCirculo. virtual void Mostrar (void); }; //---------------------------------------------------------------------------

Agora centraremos o foco na nova classe TBola. Antes, por comodidade e

clareza, definiremos um tipo enum para a direção do movimento:

Page 22: 5. Programação Orientada a Objetos em C++epdiieeulbra.synthasite.com/resources/05-POO-C++BuilderV10.pdfL U I S F E R N A N D O E S P I N O S A C O C I A N 116 5. Programação Orientada

E N G E N H A R I A D E P R O C E S S A M E N T O D I G I T A L I I

137

Em ObjGraf.h:

// Tipo definido por enumeração para a direção de TBola. Codificação: /* NO N NE 10 2 6 \ | / O 8 --- * --- 4 E / | \ 9 1 5 SO S SE */ enum TDirecao {S=1, N=2, E=4, O=8, SE=5, NE=6, SO=9, NO=10};

A declaração da classe TBola se fará em ObjGraf.h:

//--------------------------------------------------------------------------- // Definição da classe derivada TBola. // TBola deriva da classe TCirculo, que na sua // vez deriva da classe base TObjGraf class TBola: public TCirculo { private: int FDirX; // Dir. no eixo X int FDirY; // Dir. no eixo Y int FVelocidade; // Velocidade de movimento void SetDirecao (EnDirecao _Direcao); EnDirecao GetDirecao (void); public: // Construtores TBola (TPaintBox *_PaintBox, TColor _Color=clBlack, int _X=0, int _Y=0, int _Radio=1, EnDirecao _Direcao=SE, int _Velocidade=5); // Outros métodos void Mostrar (void); void Apagar (void); void Mover (void); __property int Velocidade = {read = FVelocidade, write= FVelocidade}; __property EnDirecao Direcao = {read = GetDirecao, write= SetDirecao}; }; //---------------------------------------------------------------------------

A implementação dos métodos próprios da classe TBola se fará em

ObjGraf.cpp:

//--------------------------------------------------------------------------- // Métodos associados à classe derivada TBola. // TBola deriva da classe TCirculo, que na sua // vez deriva da classe base TObjGraf TBola::TBola (TPaintBox *_PaintBox, TColor _Color, int _X, int _Y, int _Raio, EnDirecao _Direcao, int _Velocidade) : TCirculo (_PaintBox, _Color, _X, _Y, _Raio) { Direcao = _Direcao; Velocidade = _Velocidade;

Page 23: 5. Programação Orientada a Objetos em C++epdiieeulbra.synthasite.com/resources/05-POO-C++BuilderV10.pdfL U I S F E R N A N D O E S P I N O S A C O C I A N 116 5. Programação Orientada

L U I S F E R N A N D O E S P I N O S A C O C I A N

138

} //--------------------------------------------------------------------------- // Instanciação do método virtual puro da classe TObjGraf // e virtual em TCirculo. void TBola::Mostrar (void) { PaintBox->Canvas->Pen->Color = clBlack; // Observar la diferencia PaintBox->Canvas->Brush->Color = Cor; PaintBox->Canvas->Ellipse(unX, unY, unX+unRaio*2, unY+unRaio*2); } //--------------------------------------------------------------------------- // Outras funções próprias de TBola void TBola::Apagar (void) { PaintBox->Canvas->Pen->Color = PaintBox->Color; PaintBox->Canvas->Brush->Color = PaintBox->Color; PaintBox->Canvas->Ellipse(unX, unY, unX+unRaio*2, unY+unRaio*2); } //--------------------------------------------------------------------------- void TBola::Mover (void) { Apagar (); unX += FDirX * Velocidade; unY += FDirY * Velocidade; Mostrar (); } //--------------------------------------------------------------------------- void TBola :: SetDirecao (EnDirecao _Dir) { FDirY = (_Dir & 1) ? +1 : ((_Dir & 2) ? -1 : 0); FDirX = (_Dir & 4) ? +1 : ((_Dir & 8) ? -1 : 0); } //--------------------------------------------------------------------------- EnDirecao TBola::GetDirecao (void) { EnDirecao _Dir; _Dir = (EnDirecao) ((FDirY == +1) ? 1 : ((FDirY == -1 ) ? 2 : 0)); _Dir = (EnDirecao) (_Dir + (FDirX == +1) ? 4 : ((FDirX == -1 ) ? 8 :0)); return (_Dir); } //---------------------------------------------------------------------------

Finalmente, para ilustrar o polimorfismo nos embassamos na existência

de diferentes métodos com o mesmo nome Mostrar() que provoca diferentes ações

dependendo do tipo de objeto a que se aplica.

A seguir vamos criar dinâmicamente quatro objetos de classes diferentes.

Esses objetos serão referenciados (mediante ponteiros) desde um vetor de objetos

do tipo TObjGraf*. O polimorfismo vai se manifestar invocando a função

Mostrar() para cada um desses objetos.

Na unidade UPrincipal.cpp declarar a variável global:

TCirculo *Cir1, *Cir2;

Page 24: 5. Programação Orientada a Objetos em C++epdiieeulbra.synthasite.com/resources/05-POO-C++BuilderV10.pdfL U I S F E R N A N D O E S P I N O S A C O C I A N 116 5. Programação Orientada

E N G E N H A R I A D E P R O C E S S A M E N T O D I G I T A L I I

139

TQuadrado *Quad1, *Quad2; TObjGraf **Objs;

A linha acima se interpreta como: Objs é um ponteiro para uma região da

memória que conterá ponteiros do tipo TObjGraf.

Assim, em UPrincipal.cpp:

//--------------------------------------------------------------------------- void __fastcall TFrmPrincipal::FormCreate(TObject *Sender) { Objs = new TObjGraf * [4]; Objs[0] = new TCirculo (PaintBox, clBlue, 50, 50, 30); Objs[1] = new TCirculo (PaintBox, clRed, 210, 40, 70); Objs[2] = new TQuadrado (PaintBox, clGreen, 320, 150, 45); Objs[3] = new TQuadrado (PaintBox, clWhite, 190, 30, 40); } //--------------------------------------------------------------------------- void __fastcall TFrmPrincipal::FormDestroy(TObject *Sender) { for (int i=0; i<4; i++) delete Objs[i]; delete []Objs; } //--------------------------------------------------------------------------- void __fastcall TFrmPrincipal::PaintBoxPaint(TObject *Sender) { for (int i=0; i<4; i++) Objs[i]->Mostrar(); // POLIMORFISMO } //---------------------------------------------------------------------------

Neste ponto o projeto deve aparecer como antigamente.