Esta é uma pré-visualização de arquivo. Entre para ver o arquivo original
Polimorfismo BCC702-Programação de Computadores II Emiliana Mara Lopes Simões simoes.eml@gmail.com Universidade Federal de Ouro Preto maio 2010 Relembrando... Na aula passada vimos um exemplo de herança em C++ Exemplo 1: Implementação da classe Retangulo Exemplo 1: Implementar uma classe para representar um retângulo Exemplo 1: Implementação da classe Retangulo Diagrama de classe Exemplo 1: Implementação da classe Retangulo class Retangulo{ private: double ladoa; double ladob; public: Retangulo(double a, double b); double getLadoa(); double getLadob(); double area(); void imprimir(); }; Arquivo: Retangulo.h Exemplo 1: Implementação da classe Retangulo #include “Retangulo.h” #include <iostream> using namespace std; Retangulo::Retangulo(double a, double b){ ladoa = a; ladob = b; } double Retangulo::getLadoa(){ return ladoa; } ... Arquivo: Retangulo.cpp Exemplo 1: Implementação da classe Retangulo ... double Retangulo::getLadob(){ return ladob; } double Retangulo::area(){ return ladoa * ladob; } void Retangulo::imprimir(){ cout << “Retangulo com lados: ” << ladoa << “ e ” << ladob << endl << “Area: ” << area() << endl << endl; } Arquivo: Retangulo.cpp Exemplo 2: Implementação da classe Paralelepipedo Exemplo 2: A partir da classe Retangulo (figura plana) criar a classe Paralelepipedo (Figura Espacial). Exemplo 2: Implementação da classe Paralelepipedo Exemplo 2: Implementação da classe Paralelepipedo #include “Retangulo.h” class Paralelepipedo : public Retangulo{ private: double ladoc; public: Paralelepipedo(double a, double b, double c); double getLadoc(); double volume(); double area(); void imprimir(); }; Arquivo: Paralelepipedo.h Exemplo 2: Implementação da classe Paralelepipedo #include “Paralelepipedo.h” #include <iostream> using namespace std; Paralelepipedo::Paralelepipedo(double a,double b,double c) : Retangulo(a, b){ ladoc = c; } double Paralelepipedo::getLadoc(){ return ladoc; } ... Arquivo: Paralelepipedo.cpp Exemplo 2: Implementação da classe Paralelepipedo ... double Paralelepipedo::volume(){ return Retangulo::area() * ladoc; } double Paralelepipedo::area(){ return 2 * ( Retangulo::area() + getLadoa()*ladoc + ladoc*getLadob() ); } ... Arquivo: Paralelepipedo.cpp Exemplo 2: Implementação da classe Paralelepipedo ... void Paralelepipedo::imprimir(){ cout << “Paralelepipedo com Comprimento: ” << getLadoa() << endl << “Largura: ” << getLadob() << endl << “Altura: ” << ladoc << endl << “Area: ” << area() << endl << “Volume: ” << volume() << endl << endl; } ... Arquivo: Paralelepipedo.cpp Atribuições Permitidas entre Objetos de Classe Básica e de Classe Derivada e Ponteiros Apontar um ponteiro de classe básica para um objeto de classe básica int main(){ Retangulo r(2, 3); //instancia objeto Retangulo *pr; //declara um ponteiro para um Retangulo pr = &r; //faz pr apontar para o objeto r pr->imprimir(); //imprime os dados do Retangulo r system(“pause”); } Arquivo: Principal.cpp Atribuições Permitidas entre Objetos de Classe Básica e de Classe Derivada e Ponteiros Saída: ––––––––––––––––––––––––––––––––––––––––––- Retangulo com lados 2 e 3 Area: 6 Pressione uma tecla para continuar... ––––––––––––––––––––––––––––––––––––––––––- Atribuições Permitidas entre Objetos de Classe Básica e de Classe Derivada e Ponteiros Apontar um ponteiro de classe derivada para um objeto de classe derivada int main(){ Paralelepipedo p(5, 10, 3); //instancia objeto Paralelepipedo *pp; //declara ponteiro Paralelepipedo pp = &p; //faz pp apontar para o objeto p pp->imprimir(); //imprime os dados do Paralelepipedo p system(“pause”); } Arquivo: Principal.cpp Atribuições Permitidas entre Objetos de Classe Básica e de Classe Derivada e Ponteiros Saída: ––––––––––––––––––––––––––––––––––––––––––- Paralelepipedo com Comprimento: 5 Largura: 10 Altura: 3 Area: 190 Volume: 150 Pressione uma tecla para continuar... ––––––––––––––––––––––––––––––––––––––––––- Atribuições Permitidas entre Objetos de Classe Básica e de Classe Derivada e Ponteiros Apontar um ponteiro de classe básica para um objeto de classe derivada int main(){ Paralelepipedo p(5, 10, 3); //instancia objeto Retangulo *pr; //declara um ponteiro para um Retangulo pr = &p; //faz pr apontar para o objeto p pr->imprimir(); //chama a função imprimir de Retangulo system(“pause”); } Arquivo: Principal.cpp Atribuições Permitidas entre Objetos de Classe Básica e de Classe Derivada e Ponteiros Saída: ––––––––––––––––––––––––––––––––––––––––––- Retangulo com lados 5 e 10 Area: 50 Pressione uma tecla para continuar... ––––––––––––––––––––––––––––––––––––––––––- Atribuições Permitidas entre Objetos de Classe Básica e de Classe Derivada e Ponteiros Apontar um ponteiro de classe básica para um objeto de classe derivada é permitido porque um objeto da classe derivada é um objeto da classe básica Porém, o objeto da classe derivada é manipulado como um objeto da classe básica. O tipo do ponteiro determina qual função deve ser chamada! Atribuições Permitidas entre Objetos de Classe Básica e de Classe Derivada e Ponteiros Resumo das Atribuições Permitidas entre Objetos de Classe Básica e de Classe Derivada e Ponteiros Atribuições Permitidas: 1 Apontar um ponteiro de classe básica para um objeto de classe básica 2 Apontar um ponteiro de classe derivada para um objeto de classe derivada 3 Apontar um ponteiro de classe básica para um objeto de classe derivada Atribuição Proibida: 1 Apontar um ponteiro de classe derivada para um objeto de classe básica. (Erro de compilação!) Resumo das Atribuições Permitidas entre Objetos de Classe Básica e de Classe Derivada e Ponteiros Atribuições Permitidas: 1 Apontar um ponteiro de classe básica para um objeto de classe básica 2 Apontar um ponteiro de classe derivada para um objeto de classe derivada 3 Apontar um ponteiro de classe básica para um objeto de classe derivada Atribuição Proibida: 1 Apontar um ponteiro de classe derivada para um objeto de classe básica. (Erro de compilação!) Resumo das Atribuições Permitidas entre Objetos de Classe Básica e de Classe Derivada e Ponteiros Atribuições Permitidas: 1 Apontar um ponteiro de classe básica para um objeto de classe básica 2 Apontar um ponteiro de classe derivada para um objeto de classe derivada 3 Apontar um ponteiro de classe básica para um objeto de classe derivada Atribuição Proibida: 1 Apontar um ponteiro de classe derivada para um objeto de classe básica. (Erro de compilação!) Resumo das Atribuições Permitidas entre Objetos de Classe Básica e de Classe Derivada e Ponteiros Atribuições Permitidas: 1 Apontar um ponteiro de classe básica para um objeto de classe básica 2 Apontar um ponteiro de classe derivada para um objeto de classe derivada 3 Apontar um ponteiro de classe básica para um objeto de classe derivada Atribuição Proibida: 1 Apontar um ponteiro de classe derivada para um objeto de classe básica. (Erro de compilação!) Resumo das Atribuições Permitidas entre Objetos de Classe Básica e de Classe Derivada e Ponteiros Atribuições Permitidas: 1 Apontar um ponteiro de classe básica para um objeto de classe básica 2 Apontar um ponteiro de classe derivada para um objeto de classe derivada 3 Apontar um ponteiro de classe básica para um objeto de classe derivada Atribuição Proibida: 1 Apontar um ponteiro de classe derivada para um objeto de classe básica. (Erro de compilação!) Resumo das Atribuições Permitidas entre Objetos de Classe Básica e de Classe Derivada e Ponteiros Atribuições Permitidas: 1 Apontar um ponteiro de classe básica para um objeto de classe básica 2 Apontar um ponteiro de classe derivada para um objeto de classe derivada 3 Apontar um ponteiro de classe básica para um objeto de classe derivada Atribuição Proibida: 1 Apontar um ponteiro de classe derivada para um objeto de classe básica. (Erro de compilação!) Declaração de funções virtual: Implementação da classe Retangulo class Retangulo{ private: double ladoa; double ladob; public: Retangulo(double a, double b); double getLadoa(); double getLadob(); virtual double area(); virtual void imprimir(); }; Arquivo: Retangulo.h Arquivo Retangulo.cpp não é alterado: Implementação da classe Retangulo #include “Retangulo.h” #include <iostream> using namespace std; Retangulo::Retangulo(double a, double b){ ladoa = a; ladob = b; } double Retangulo::getLadoa(){ return ladoa; } ... Arquivo: Retangulo.cpp Arquivo Retangulo.cpp não é alterado: Implementação da classe Retangulo ... double Retangulo::getLadob(){ return ladob; } double Retangulo::area(){ return ladoa * ladob; } void Retangulo::imprimir(){ cout << “Retangulo com lados: ” << ladoa << “ e ” << ladob << endl << “Area: ” << area() << endl << endl; } Arquivo: Retangulo.cpp Declaração de funções virtual: Implementação da classe Paralelepipedo #include “Retangulo.h” class Paralelepipedo : public Retangulo{ private: double ladoc; public: Paralelepipedo(double a, double b, double c); double getLadoc(); double volume(); virtual double area(); virtual void imprimir(); }; Arquivo: Paralelepipedo.h Arquivo Paralelepipedo.cpp não é alterado: Implementação da classe Paralelepipedo #include “Paralelepipedo.h” #include <iostream> using namespace std; Paralelepipedo::Paralelepipedo(double a,double b,double c) : Retangulo(a, b){ ladoc = c; } double Paralelepipedo::getLadoc(){ return ladoc; } ... Arquivo: Paralelepipedo.cpp Arquivo Paralelepipedo.cpp não é alterado: Implementação da classe Paralelepipedo ... double Paralelepipedo::volume(){ return Retangulo::area() * ladoc; } double Paralelepipedo::area(){ return 2 * ( Retangulo::area() + getLadoa()*ladoc + ladoc*getLadob() ); } ... Arquivo: Paralelepipedo.cpp Arquivo Paralelepipedo.cpp não é alterado: Implementação da classe Paralelepipedo ... void Paralelepipedo::imprimir(){ cout << “Paralelepipedo com Comprimento: ” << getLadoa() << endl << “Largura: ” << getLadob() << endl << “Altura: ” << ladoc << endl << “Area: ” << area() << endl << “Volume: ” << volume() << endl << endl; } ... Arquivo: Paralelepipedo.cpp Declaração de funções virtual Funções são declaradas como virtual para que seja implementado o comportamento polimórfico Polimorfismo = Várias formas O termo polimorfismo é usado para descrever o processo pelo qual diferentes implementações de uma função podem ser acessadas usando o mesmo nome O que muda? O tipo do objeto apontado, não o tipo do ponteiro, determina qual a versão da função virtual deve ser chamada! Exemplo de polimorfismo #in c l u d e " P a r a l e l e p i p e d o . h" #in c l u d e <ios t r eam> us i ng namespace s t d ; vo id main ( ) { i n t op ; doub le a , b , c ; Retangu lo ∗ f i g [ 1 0 ] ; f o r ( i n t i =0; i <10; i++){ cout<<" D i g i t e : \ n1− I n s e r i r Retangu lo ; \ n2− I n s e r i r P a r a l e l e p i p e d o . \ n>" ; c in>>op ; i f ( op == 1) { cout<<" D i g i t e os v a l o r e s dos l a d o s a e b do r e t a n gu l o : " ; Exemplo de polimorfismo c i n >> a >> b ; f i g [ i ] = new Retangu lo ( a , b ) ; } e l s e { cout<<" D i g i t e os v a l o r e s dos l a d o s a , b e c do p a r a l e l e p i p e d o : " ; c i n >> a >> b >> c ; f i g [ i ] = new Pa r a l e l e p i p e d o ( a , b , c ) ; } } f o r ( i n t i =0; i <10; i++) f i g [ i ]−>imp r im i r ( ) ; system ( " pause " ) ; } Funções Virtuais Puras Para criar uma função virtual pura coloca-se “= 0” em sua declaração: v i r t u a l <t ipo_re to rno> nome_funcao(<parametros >) = 0 ; Uma função virtual pura é aquela declarada em uma classe, porém sem implementação Funções Virtuais Puras e Classes Abstratas Assim, no exemplo que segue, a função area() é uma função virtual pura c l a s s F i gu r a { p r i v a t e : doub le x , y ; p ub l i c : vo id setDim ( doub le i , doub le j ) {// funcao normal x = i ; y = j ; } v i r t u a l vo i d a r ea ( ) = 0 ; // funcao v i r t u a l pura } ; Se uma classe tem pelo menos uma função virtual pura, ela é considerada uma classe abstrata Funções Virtuais Puras e Classes Abstratas Uma classe abstrata tem uma característica importante: Não pode ser usada para instanciar objetos! As classes abstratas são muito genéricas para definir objetos reais A classe abstrata normalmente é usada como uma classe básica em uma hierarquia de herança Ainda assim, uma classe abstrata também pode ser usada para declarar ponteiros necessários para suportar polimorfismo Funções Virtuais Puras e Classes Abstratas Uma classe abstrata tem uma característica importante: Não pode ser usada para instanciar objetos! As classes abstratas são muito genéricas para definir objetos reais A classe abstrata normalmente é usada como uma classe básica em uma hierarquia de herança Ainda assim, uma classe abstrata também pode ser usada para declarar ponteiros necessários para suportar polimorfismo Funções Virtuais Puras e Classes Abstratas Uma classe abstrata tem uma característica importante: Não pode ser usada para instanciar objetos! As classes abstratas são muito genéricas para definir objetos reais A classe abstrata normalmente é usada como uma classe básica em uma hierarquia de herança Ainda assim, uma classe abstrata também pode ser usada para declarar ponteiros necessários para suportar polimorfismo Funções Virtuais Puras e Classes Abstratas Uma classe abstrata tem uma característica importante: Não pode ser usada para instanciar objetos! As classes abstratas são muito genéricas para definir objetos reais A classe abstrata normalmente é usada como uma classe básica em uma hierarquia de herança Ainda assim, uma classe abstrata também pode ser usada para declarar ponteiros necessários para suportar polimorfismo Exemplo de Hierarquia de Herança com Classe Abstrata Não faz sentido calcular a área de uma figura, sem saber de que figura se trata É possível calcular a área de retângulos, triângulos e círculos Exemplo de Hierarquia de Herança com Classe Abstrata Não faz sentido calcular a área de uma figura, sem saber de que figura se trata É possível calcular a área de retângulos, triângulos e círculos Exemplo de Hierarquia de Herança com Classe Abstrata Não faz sentido calcular a área de uma figura, sem saber de que figura se trata É possível calcular a área de retângulos, triângulos e círculos Dúvidas? Próxima Aula Templates