Post on 13-Feb-2019
PolimorfismoBCC 221 - Programacao Orientada a Objectos(POO)
Guillermo Camara-Chavez
Departamento de Computacao - UFOPBaseado nos slides do Prof. Marco Antonio Carvalho
1/104
Introducao
I O Polimorfismo e um recurso que nos permite programar“em geral” ao inves de programar especıficamente ;
I Vamos supor um programa que simula o movimento de variosanimais.
2/104
Introducao
I Tres classes representam os animais pesquisados:
I Peixe;
I Sapo;
I Passaro
I Todos herdam da classe Animal
I Contem um metodo mover e a posicao do animal.
3/104
Introducao (cont.)
I Cada classe derivada implementa o metodo mover();
I O programa mantem um vetor de ponteiros para objetosdas classes derivadas da classe Animal
I Para simular o movimento do animal, envia-se a mesmamensagem (mover()) para cada objeto;
4/104
Introducao (cont.)
I Cada objeto respondera de uma maneira diferente;
I A mensagem e enviada genericamente
I Cada objeto sabe como modificar sua posicao de acordo comseu tipo de movimento.
5/104
Introducao (cont.)
6/104
Introducao (cont.)
I Atraves do polimorfismo pode-se projetar e implementarsistemas que sejam facilmente extensıveis
I Novas classes podem ser adicionadas com pouca oumesmo nenhuma modificacao as partes gerais do programa
I As novas classes devem fazer parte da hierarquia de heranca.
7/104
Introducao (cont.)
I Por exemplo, se criarmos uma classe Tartaruga somenteprecisamos implementar:
I a classe e,
I a parte da simulacao que instancia o objeto
I As partes que processam a classe Animal genericamente naoseriam alteradas.
8/104
Outro Exemplo
I Vamos imaginar que temos um programa que controla umjogo que contem as seguintes classes/objetos/elementos
I Marciano;
I Plutoniano;
I RaioLaser;
I NaveEspacial.
I Todos estes objetos sao derivados de uma classeObjetoEspacial
9/104
Polimorfismo
I Para gerenciar os elementos presentes na tela, mantemos umvetor com ponteiros para objetos da classe ObjetoEspacial
I Cada objeto possui um metodo desenhar(), que o imprime natela.
10/104
Polimorfismo (cont.)
I Para atualizar a tela do jogo, e necessario redesenhar todosos seus elementos.
I Enviar a mesma mensagem para cada objeto do vetor
I Metodo desenhar();
11/104
Polimorfismo (cont.)
I Metodo desenhar():
I Cada objeto redefine este metodo para suas especificidades;
I A classe ObjetoEspacial determina que as classes derivadas oimplementem.
I Podem ser criadas novas classes para outros elementos dojogo
I O processo de atualizar a tela continuaria o mesmo.
12/104
Outro Exemplo
13/104
Outro Exemplo (cont.)
I Vamos supor um programa que simula diversos animaisemitindo sons.
I Cada personagem emite seu proprio som
I Cada personagem e um objeto que invoca seu proprio metodoemitirSom();
I A classe derivada sabe como deve ser implementado.
I Em uma hierarquia de heranca, podemos criar uma classeMamifero, a partir dela derivam Boi, cachorro, gato, bode,etc.
14/104
Implementacoes
c l a s s Mamifero{p u b l i c :
v o i d emit i rSom ( ){ cout << "\nsom de mamifero" ; } ;} ;c l a s s Cachor ro : p u b l i c Mamifero{p u b l i c :
v o i d emit i rSom ( ){ cout << "\n woof woof" ; } ;} ;c l a s s Vaca : p u b l i c Mamifero{p u b l i c :
v o i d emit i rSom ( ){ cout << "\n moo moo" ; } ;} ;c l a s s Bode : p u b l i c Mamifero{p u b l i c :
v o i d emit i rSom ( ){ cout << "\n baa baa" ; } ;} ;c l a s s Gato : p u b l i c Mamifero{p u b l i c :
v o i d emit i rSom ( ){ cout << "\n meow meow" ; } ;} ;
15/104
Sem Polimorfismo
i n t main ( ){Cachor ro c a c h o r r o ;Vaca vaca ;Bode bode ;Gato gato ;c a c h o r r o . emit i rSom ( ) ;vaca . emit i rSom ( ) ;bode . emit i rSom ( ) ;gato . emit i rSom ( ) ;r e t u r n 0 ;
}
16/104
Sem Polimorfismo (cont.)
woof woofmoo moobaa baameow meow
17/104
Polimorfismo
c l a s s Mamifero{p u b l i c :
v i r t u a l v o i d emit i rSom ( ){ cout << "\nsom de mamifero" ; } ;} ;c l a s s Cachor ro : p u b l i c Mamifero{p u b l i c :
v o i d emit i rSom ( ){ cout << "\n woof woof" ; } ;} ;c l a s s Vaca : p u b l i c Mamifero{p u b l i c :
v o i d emit i rSom ( ){ cout << "\n moo moo" ; } ;} ;c l a s s Bode : p u b l i c Mamifero{p u b l i c :
v o i d emit i rSom ( ){ cout << "\n baa baa" ; } ;} ;c l a s s Gato : p u b l i c Mamifero{p u b l i c :
v o i d emit i rSom ( ){ cout << "\n meow meow" ; } ;} ;
18/104
Polimorfismo (cont.)
i n t main ( ){Mamifero∗ p [ 5 ] = {
new Cachor ro ( ) ,new Vaca ( ) ,new Bode ( ) ,new Gato ( ) } ; }
f o r ( i n t i = 0 ; i < 5 ; i ++){
p [ i ]−>emit i rSom ( ) ;}r e t u r n 0 ;
}
19/104
Polimorfismo (cont.)
woof woofmoo moobaa baameow meow
20/104
Polimorfismo (cont.)
I Como vimos na aula anterior, e possıvel realizar a conversaode tipo entre classe base e derivada
I Um objeto da classe base pode receber um objeto da classederivada
I O contrario nao vale
21/104
Polimorfismo (cont.)
I Tambem e possıvel fazer o mesmo com ponteiros
I Um ponteiro para a classe base pode apontar para um objetoda classe derivada
I O contrario nao vale.
22/104
Polimorfismo (cont.)
I Note que a classe Derivadaredefine o metodo print();
I O metodo original imprimeos atributos a, b e c ;
I O metodo redefinidoacrescenta a impressao dosatributos d , e e f .
Base
–a: int–b: int–c: int
+Base()+getABC()+setABC()+print()
Derivada
–d: int–e: int–f: int
+Derivada()+getDEF()+setDEF()+print()
23/104
Polimorfismo (cont.)
c l a s s Base{i n t a , b , c ;
p u b l i c :Base ( i n t a=0, i n t b=0, i n t c =0): a ( a ) , b ( b ) , c ( c ){}v o i d p r i n t ( ){
cout << "\n Base: "
<< a << ","<< b << "," <<c ;}
} ;c l a s s D e r i v a d a : p u b l i c Base{
i n t d , e , f ;p u b l i c :
D e r i v a d a ( i n t d=0, i n t e =0, i n t f =0): d ( d ) , e ( e ) , f ( f ){}v o i d p r i n t ( ){
cout << "\n Derivada"
<< d << ","<< e << "," <<f ;}
} ;
24/104
Polimorfismo (cont.)
#i n c l u d e <i o s t r e a m>#i n c l u d e "base.h"
u s i n g namespace s t d ;i n t main ( ) {
Base objB ( 1 , 2 , 3 ) , ∗ p objB=n u l l p t r ;D e r i v a d a objD ( 4 , 5 , 6 ) , ∗ p objD=n u l l p t r ;
p objB = &objB ;p objB−>p r i n t ( ) ;p objD = &objD ;P−objD−>p r i n t ( ) ;p objB = &objD ;p objB−>p r i n t ( ) ;
}
25/104
Polimorfismo (cont.)
#i n c l u d e <i o s t r e a m>#i n c l u d e "base.h"
u s i n g namespace s t d ;i n t main ( ) {
Base objB ( 1 , 2 , 3 ) , ∗ p objB=n u l l p t r ;D e r i v a d a objD ( 4 , 5 , 6 ) , ∗ p objD=n u l l p t r ;
p objB = &objB ; // aponta para objeto da classe Basep objB−>p r i n t ( ) ; // invoca metodo da classe Basep objD = &objD ; // aponta para objeto da classe DerivadaP−objD−>p r i n t ( ) ; // invoca metodo da classe Derivadap objB = &objD ; // aponta para objeto da classe Derivadap objB−>p r i n t ( ) ; // invoca metodo da classe Baser e t u r n 0 ;
}
26/104
Polimorfismo (cont.)
Base
D e r i v a d a
Base
27/104
Polimorfismo (cont.)
I Este tipo de construcao e permitido pelo compilador porconta do relacionamento de heranca
I Um objeto da classe derivada e um objeto da classe base.
28/104
Polimorfismo (cont.)
I A funcionalidade invocada depende do handle (tipo doponteiro ou referencia) utilizado para invoca-la
I Nao depende do tipo do objeto apontado pelo handle.
I Utilizando um tipo especial de metodo podemos fazer comque este comportamento seja invertido
I O que e crucial para o polimorfismo.
29/104
Polimorfismo (cont.)
#i n c l u d e <i o s t r e a m>#i n c l u d e "base.h"
u s i n g namespace s t d ;i n t main ( ) {
Base objB ( 1 , 2 , 3 ) , ∗ p objB=n u l l p t r ;D e r i v a d a objD ( 4 , 5 , 6 ) , ∗ p objD=n u l l p t r ;
p objB = &objB ; // aponta para objeto da classe Basep objB−>p r i n t ( ) ; // invoca metodo da classe Base
// ERRO! nao e possıvel apontar para objeto da classe Basep objD = &objB ;// Erro! Um objeto da classe base nao// e um objeto da classe derivadap objD−>p r i n t ( ) ;r e t u r n 0 ;
}
30/104
Funcoes Virtuais
I O tipo do handle determina a versao de um metodo que serainvocada
I Nao o tipo do objeto apontado
Base ∗ p objB=n u l l p t r ;D e r i v a d a objD ( 4 , 5 , 6 ) ;
p objB = &objD ; // aponta para objeto da classe Derivadap objB−>p r i n t ( ) ; // invoca metodo da classe Base
31/104
Funcoes Virtuais (cont.)
I Com funcoes virtuais, ocorre o contrario
I O tipo do objeto apontado determina qual sera a versao dometodo a ser invocado
32/104
Funcoes Virtuais (cont.)
I Voltando ao exemplo do jogo espacial, cada classe derivada daclasse ObjetoEspacial define um objeto de formatogeometrico diferente
I Cada classe define seu proprio metodo desenhar()
I Podemos atraves de um ponteiro para classe base invocar ometodo desenhar();
I Porem, seria util se o programa determinassedinamicamente (tempo de execucao) qual metodo deveser utilizado para desenhar cada forma, baseado no tipo doobjeto.
33/104
Funcoes Virtuais (cont.)
I Para permitir este tipo de comportamento dinamico,declaramos na classe base o metodo desenhar() como umafuncao virtual
I O redefinimos nas classes derivadas;
I O metodo sobrescrito possui o mesmo prototipo do original(assinatura e tipo de retorno).
34/104
Funcoes Virtuais (cont.)
I Para declararmos um metodo como virtual, adicionamos apalavra chave virtual antes de seu prototipo
v i r t u a l v o i d d e s e n h a r ( )
I Se uma classe nao sobrescrever um metodo virtual, ela herdaa implementacao original;
35/104
Funcoes Virtuais (cont.)
I Definindo o metodo como virtual na classe base, elepermanecera assim por toda a hierarquia de heranca
I Mesmo que as classes derivadas a sobrescrevam e nao adeclarem como virtual novamente;
I E uma boa pratica declarar o metodo como virtual por toda ahierarquia de classes.
36/104
Resolucao Estatica e Dinamica
I As instrucoes de chamada a metodos nao virtuais saoresolvidas em tempo de compilacao
I E traduzidas em chamadas a funcoes de endereco fixo;
I Isso faz com que a instrucao seja vinculada a funcao antes desua execucao;
37/104
Resolucao Estatica e Dinamica (cont.)
I Resolucao Estatica
I Acontece quando invocamos um metodo atraves de um objeto,usando o operador .
I Nao se trata de comportamento polimorfico
38/104
Resolucao Dinamica
I Quando uma instrucao de chamada a um metodo virtual eencontrada pelo compilador, ele nao tem como identificarqual e o metodo associado em tempo de compilacao.
I Quando utilizamos ponteiros (ou referencias) para objetos,o compilador nao conhece qual e a classe do enderecocontido no ponteiro antes de o programa ser executado;
I A instrucao e avaliada em tempo de execucao;
I Isto e chamado de Resolucao Dinamica, ou Resolucao Tardia(Comportamento polimorfico).
39/104
Exemplo
Poligono
–base–altura
+setValores()+calculaArea()
Retangulo
+calculaArea()
Triangulo
+calculaArea()
40/104
Exemplo (cont.)
c l a s s P o l i g o n o {
p r o t e c t e d :d o u b l e base , a l t u r a ;
p u b l i c :
v o i d s e t V a l o r e s ( d o u b l e a , d o u b l e b ){base=a ;a l t u r a=b ;
}
v i r t u a l d o u b l e a r e a ( v o i d ) {r e t u r n 0 ;
}}
41/104
Exemplo (cont.)
c l a s s Re t a ng u lo : p u b l i c P o l i g o n o {p u b l i c :
d o u b l e a r e a ( v o i d ){r e t u r n ( base ∗ a l t u r a ) ;
}} ;
c l a s s T r i a n g u l o : p u b l i c P o l i g o n o {p u b l i c :
d o u b l e a r e a ( v o i d ){r e t u r n ( base ∗ a l t u r a / 2 ) ;
}} ;
42/104
Exemplo (cont.)
i n t main ( ) {R et a n gu l o r e c t ;T r i a n g u l o t r g l ;P o l i g o n o p o l y ;
P o l i g o n o ∗ p p o l y 1 = &r e c t ;P o l i g o n o ∗ p p o l y 2 = &t r g l ;P o l i g o n o ∗ p p o l y 3 = &p o l y ;
ppoly1−>s e t V a l o r e s ( 4 , 5 ) ;ppoly2−>s e t V a l o r e s ( 4 , 5 ) ;ppoly3−>s e t V a l o r e s ( 4 , 5 ) ;
cout << ppoly1−>a r e a ( ) << e n d l ;cout << ppoly2−>a r e a ( ) << e n d l ;cout << ppoly3−>a r e a ( ) << e n d l ;r e t u r n 0 ;
}
43/104
Exemplo (cont.)
I As tres classes (Poligono, Retangulo e Triangulo)possuem os mesmos membros: base, altura, setValores()e area().
I area() foi definida como virtual porque e redefinida depoisnas classes derivadas.
44/104
Outro Exemplo
I Considere uma classe Veıculo com duas classes derivadasAutomovel e Bicicleta
I Essas classes tem tres metodos, definidos para veıculos deforma geral e redefinidas mais especificamente paraautomoveis e bicicletas;
45/104
Outro Exemplo (cont.)
I As funcoes sao:
I VerificaLista(): para verificar o que precisa ser analisadono veıculo;
I Reparar(): para realizar os reparos e a manutencao necessaria
I Limpa(): para realizar procedimentos de limpeza do veıculo
I A aplicacao Oficina define um objeto que recebe objetos daclasse Veıculos.
I Para cada veıculo recebido, a oficina executa na sequencia ostres metodos da classe Veıculo.
46/104
Outro Exemplo (cont.)
c l a s s V e i c u l o{p u b l i c :
v i r t u a l v o i d v e r i f i c a L i s t a ( ){cout<<"\n Verifica Veiculo" ;
} ;v i r t u a l v o i d r e p a r a r ( ){
cout<<"\n Repara Veiculo" ;} ;v i r t u a l v o i d l i m p a ( ){
cout<<"\n Limpa Veiculo" ;} ;
} ;
47/104
Outro Exemplo (cont.)
c l a s s Automovel : p u b l i c V e i c u l o{p u b l i c :
v o i d v e r i f i c a L i s t a ( ){ cout<<"\n Verifica Automovel" ; } ;v o i d r e p a r a r ( ){ cout<<"\n Repara Automovel" ; } ;v o i d l i m p a ( ){ cout<<"\n Limpa Automovel" ; } ;
} ;
c l a s s B i c i c l e t a : p u b l i c V e i c u l o{p u b l i c :
v o i d v e r i f i c a L i s t a ( ){ cout<<"\n Verifica Bicicleta" ; } ;v o i d r e p a r a r ( ){ cout<<"\n Repara Bicicleta" ; } ;v o i d l i m p a ( ){ cout<<"\n Limpa Bicicleta" ; } ;
} ;
48/104
Outro Exemplo (cont.)
I Nao ha como saber no momento de programacao se aOficina estara recebendo um automovel ou uma bicicleta
I O momento de decisao sobre qual metodo sera aplicado soocorrera durante a execucao do programa.
49/104
Outro Exemplo (cont.)
c l a s s O f i c i n a{
i n t R ;p u b l i c :
V e i c u l o ∗ prox imo ( ) ;v o i d manter ( V e i c u l o ∗ v ) ;i n t getR ( ) ;
} ;
50/104
Outro Exemplo (cont.)
V e i c u l o ∗ O f i c i n a : : prox imo ( ){V e i c u l o ∗v ;R = rand ( ) ;i f (R % 2 == 0)
v = new Automovel ( ) ;e l s e
v = new B i c i c l e t a ( ) ;r e t u r n v ;
}v o i d O f i c i n a : : manter ( V e i c u l o ∗ v ){
v−>V e r i f i c a L i s t a ( ) ;v−>Reparar ( ) ;v−>Limpa ( ) ;
}i n t O f i c i n a : : getR ( ){
r e t u r n R ;}
51/104
Outro Exemplo (cont.)
i n t main ( ){
O f i c i n a Of ;V e i c u l o ∗pv ;i n t n = 0 ;w h i l e ( n < 6){
pv = Of . prox imo ( ) ;cout<<end l<<Of . getR()<< e n d l ;Of . manter ( pv ) ;n++;d e l e t e pv ;
}r e t u r n 0 ;
}
52/104
Outro Exemplo (cont.)
Na tela e mostrado
41V e r i f i c a B i c i c l e t aRepara B i c i c l e t aLimpa B i c i c l e t a
18467V e r i f i c a B i c i c l e t aRepara B i c i c l e t aLimpa B i c i c l e t a
6334V e r i f i c a AutomovelRepara AutomovelLimpa Automovel
26500V e r i f i c a AutomovelRepara AutomovelLimpa Automovel
19169V e r i f i c a B i c i c l e t aRepara B i c i c l e t aLimpa B i c i c l e t a
15724V e r i f i c a AutomovelRepara AutomovelLimpa Automovel
53/104
Outro Exemplo (cont.)
I O metodo Of.proximo() realiza uma atribuicao de
I um objeto Automovel a variavel R quando o valor do numeroaleatorio gerado e par.
I um objeto Bicicleta a variavel R quando o valor do numeroaleatorio gerado e ımpar.
54/104
Sumario das Atribucoes permitidas entre Ponteiros deClasse Base e Derivada
I Apesar de um objeto de uma classe derivada ser um objetoda classe base, temos dois tipos de objetos completamentediferentes.
I um objeto de uma classe derivada pode ser tratado comoum objeto da classe base
I Ele contem todos os membros da classe base.
55/104
Sumario das Atribucoes permitidas entre Ponteiros deClasse Base e Derivada (cont.)
I O contrario nao e valido (objeto da classe Base ser tratadocomo da classe Derivada)
I Os membros da classe derivada sao indefinidos para objetosda classe base;
I E possıvel realizar um downcasting;
I No entanto, nao e seguro
56/104
Sumario das Atribucoes Permitidas
Considere o seguinte caso:
c l a s s Base{p u b l i c :
Base ( ) {}v o i d p r i n t ( ){
cout << "\n Base" ;}
} ;c l a s s D e r i v a d a : p u b l i c Base{p u b l i c :
D e r i v a d a ( ){}v o i d p r i n t ( ){
cout << "\n Derivada" ;}v o i d p r i n t 2 {}{
cout << "\n Interno" ; "}
};
i n t main ( ) {Base objB ,
∗ p objB=n u l l p t r ;D e r i v a d a objD ,
∗p objD=n u l l p t r ;. . .r e t u r n 0 ;
}
57/104
Sumario das Atribucoes Permitidas (cont.)
I Apontar um ponteiro base para um objeto base e simples
p objB = &objB ;
I Apontar um ponteiro derivado para um objeto derivado esimples
p objD = &objD ;
58/104
Sumario das Atribucoes Permitidas (cont.)
I Apontar um ponteiro base para um objeto derivado eseguro
p objB = &objD ;
I O ponteiro deve ser utilizado apenas para realizarchamadas da classe base;
p objB−>p r i n t 2 ( ) ; // ERRO nao e membro da classeBase
I Chamadas da classe derivada gerarao erros, a nao ser queseja utilizado downcasting, o que nao e seguro
59/104
Sumario das Atribucoes Permitidas (cont.)
I Apontar um ponteiro derivado para um objeto base geraum erro de compilacao
p objD = &objB ; // ERRO de compilacao
I A relacao e um se da de cima para baixo na hierarquia
60/104
Classes Abstratas e Metodos Virtuais Puros
I Quando pensamos em classes, podemos pensar que osprogramas as instanciarao, criando objetos daquele tipo
I Porem, existem casos em que e util definir classes que naoserao instanciadas nunca.
61/104
Classes Abstratas e Metodos Virtuais Puros (cont.)
I Tais classes sao denominadas classes abstratas
I Como sao normalmente utilizadas como base em hierarquias deheranca, tambem sao conhecidas como classes baseabstratas.
I Sao classes “incompletas”, que devem ser completadas porclasses derivadas;
I Por isso nao podem ser instanciadas.
62/104
Classes Abstratas
I Classes que podem ser instanciadas sao chamadas declasses concretas
I Providenciam implementacao para todos os metodos quedefinem.
I O proposito de uma classe base abstrata e exatamenteprover um base apropriada para que outras classes herdem
63/104
Classes Abstratas (cont.)
I Classes base abstratas sao genericas demais paradefinirem com precisao objetos reais e serem instanciadas
I As classes concretas cuidam das especificidadesnecessarias para que objetos sejam bem modelados einstanciados
64/104
Classes Abstratas (cont.)
I Em uma hierarquia de heranca, nao e obrigatoria a existenciade uma base abstrata
I Porem, bons projetos de engenharia de software possuemhierarquias de heranca cujo topo e formado por classesabstratas;
65/104
Classes Abstratas (cont.)
I Em alguns casos, classes abstratas constituemcompletamente os primeiros nıveis de uma hierarquia deheranca.
I Uma classe e determinada abstrata automaticamentequando um ou mais de seus metodos virtuais saodeclarados como puros.
66/104
Metodos Virtuais Puros
I Para declararmos um metodo como virtual puro, utilizamos aseguinte sintaxe:
v i r t u a l v o i d p r i n t ( ) = 0 ;
I O “=0” e conhecido como especificador puro
I Nao se trata de atribuicao;
I Metodos virtuais nao possuem implementacao;
I Toda classe derivada concreta deve sobrescreve-lo comuma implementacao concreta
67/104
Metodos Virtuais Puros (cont.)
I A diferenca entre um metodo virtual e um metodo virtualpuro e que o primeiro opcionalmente possui implementacao naclasse base
I O segundo requer obrigatoriamente uma implementacao nasclasses derivadas.
68/104
Metodos Virtuais Puros (cont.)
I Um metodo virtual puro nunca sera executada na classe base
I Deve ser sobrescrita nas classes derivadas;
I Serve para fornecer uma interface polimorfica para classesderivadas.
69/104
Metodos Virtuais Puros (cont.)
I Novamente, uma classe que possui um metodo virtualpuro nao pode ser instanciada
I Invocar um metodo virtual puro geraria erro.
I Pode-se declarar ponteiros para uma classe base abstrata eaponta-los para objetos de classes derivadas.
70/104
Exemplo de Polimorfismo
A utilizacao de polimorfismo e particularmente eficiente naimplementacao de sistemas de software em camadas
I Como um sistema operacional;
I Cada tipo de dispositivo fısico opera de uma forma diferente
I No entanto, operacoes como escrita e leitura sao basicas.
71/104
Exemplo de Polimorfismo (cont.)
I Uma classe base abstrata pode ser utilizada para geraruma interface para todos os dispositivos
I Todo o comportamento necessario pode ser implementadocomo metodos virtuais puros;
I Cada dispositivo sobrescreve os metodos em suas propriasclasses, derividas da classe base abstrata.
I Para cada novo dispositivo, instala-se o driver, que contemimplementacoes concretas para a classe base abstrata.
72/104
Outro Exemplo de Polimorfismo
Outro aplicacao util do polimorfismo e na criacao de classes deiteradores
I Iteradores sao utilizados para percorrer estruturas de dados ou(colecoes)
I Vetores, listas, arvores, etc;
I Percorrem os objetos de uma agregacao sem expor suaimplementacao interna
I A STL fornece uma grande variedade de iteradores paraestruturas de dados
73/104
Exemplo: Funcionarios
I Pagamento de funcionarios: 4 tipos de funcionarios
1. Salario fixo semanal;
2. Horistas (hora extra depois de 40 horas);
3. Comissionados;
4. Assalariados Comissionados
I A ideia e realizar o calculo dos pagamentos utilizandocomportamento polimorfico.
I Na aula sobre heranca, tınhamos apenas os dois ultimos tiposde funcionarios, em uma hierarquia de heranca.
74/104
Exemplo: Funcionarios (cont.)
75/104
Exemplo: Funcionarios (cont.)
I Neste exemplo, nao ha uma classe que absorva ocomportamento das outras
I Sera necessario criar uma outra classe que sirva de base paraos outras
I Representara um funcionario generico
I Nome, sobrenome e documento sao os atributos;
I Getters e setters para cada um dos atributos.
I Um print para todos os atributos.
I Sera uma classe base abstrata.
76/104
Exemplo: Funcionarios (cont.)
I Teremos quatro classes derivadas, cada uma representandoum tipo de funcionario
I A diferenca se da basicamente pela forma em que opagamento e calculado (metodo earnings()).
77/104
Exemplo: Funcionarios (cont.)
78/104
Exemplo: Funcionarios (cont.)
Dada a hierarquia estabelecida e a necessidade de polimorfismo:
I Os getters e setters da classe base serao metodos concretos;
I O metodo print sera um metodo virtual
I Tera implementacao, mas opcionalmente podera sersobrescrito pelas classes derivadas.
I O metodo earnings sera um metodo virtual puro
I Nao tera implementacao e obrigatoriamente sera sobrescritopelas classes derivadas.
I As classes derivadas definem seus proprios atributos erespectivos getters e setters.
79/104
Exemplo: Funcionarios (cont.)
80/104
Exemplo: Funcionarios (cont.)
81/104
Employee.h
#i f n d e f EMPLOYEE H#d e f i n e EMPLOYEE H#i n c l u d e <s t r i n g > // classe string padrao C++u s i n g s t d : : s t r i n g ;c l a s s Employee {
s t r i n g f i r s t N a m e ;s t r i n g lastName ;s t r i n g s o c i a l S e c u r i t y N u m b e r ;
p u b l i c :Employee ( c o n s t s t r i n g="" , c o n s t s t r i n g&="" ,
c o n s t s t r i n g&="" ) ;
v o i d s e t F i r s t N a m e ( c o n s t s t r i n g& ) ;s t r i n g g e t F i r s t N a m e ( ) c o n s t ;
v o i d setLastName ( c o n s t s t r i n g& ) ;s t r i n g getLastName ( ) c o n s t ;
. . .
82/104
Employee.h (cont.)
. . .v o i d s e t S o c i a l S e c u r i t y N u m b e r ( c o n s t s t r i n g& ) ;s t r i n g g e t S o c i a l S e c u r i t y N u m b e r ( ) c o n s t ;
// a funcao virtual pura cria a classe basica abstrata Employeev i r t u a l d o u b l e e a r n i n g s ( ) c o n s t = 0 ; // virtual purav i r t u a l v o i d p r i n t ( ) c o n s t ; // virtual
} ; // fim da classe Employee#e n d i f
83/104
Employee.cpp
#i n c l u d e <i o s t r e a m>u s i n g s t d : : cout ;
#i n c l u d e "Employee.h" // Definicao da classe Employee
// construtorEmployee : : Employee ( c o n s t s t r i n g &f i r s t ,
c o n s t s t r i n g &l a s t ,c o n s t s t r i n g &s s n )
: f i r s t N a m e ( f i r s t ) ,lastName ( l a s t ) ,s o c i a l S e c u r i t y N u m b e r ( s s n ) {}
} // fim do construtor Employee
84/104
Employee.cpp
// imprime informacoes de Employee (virtual, mas nao virtual pura)v o i d Employee : : p r i n t ( ) c o n s t{
cout << g e t F i r s t N a m e ( ) << ’ ’ << getLastName ( )<< "\nsocial security number: "
<< g e t S o c i a l S e c u r i t y N u m b e r ( ) ;} // fim da funcao print
85/104
HourlyEmployee.h
#i f n d e f HOURLY H#d e f i n e HOURLY H#i n c l u d e "Employee.h" // Definicao da classe Employeec l a s s Hour lyEmployee : p u b l i c Employee {
d o u b l e wage ; // salario por horad o u b l e h o u r s ; // horas trabalhadas durante a semana
p u b l i c :Hour lyEmployee ( c o n s t s t r i n g &="" , c o n s t s t r i n g &="" ,
c o n s t s t r i n g &="" , d o u b l e = 0 . 0 , d o u b l e = 0 . 0 ) ;
v o i d setWage ( d o u b l e ) ;d o u b l e getWage ( ) c o n s t ;v o i d s e t H o u r s ( d o u b l e ) ;d o u b l e getHours ( ) c o n s t ;
// palavra-chave virtual assinala intencao de sobrescreverv i r t u a l d o u b l e e a r n i n g s ( ) c o n s t ; // calcula os rendimentosv i r t u a l v o i d p r i n t ( ) c o n s t ; // imprime HourlyEmployee
} ;#e n d i f
86/104
HourlyEmployee.cpp
u s i n g s t d : : cout ;#i n c l u d e "HourlyEmployee.h" // Definicao da classe HourlyEmployee
// construtorHour lyEmployee : : Hour lyEmployee ( c o n s t s t r i n g &f i r s t ,
c o n s t s t r i n g &l a s t ,c o n s t s t r i n g &ssn ,d o u b l e hourlyWage ,d o u b l e hoursWorked )
: Employee ( f i r s t , l a s t , s s n ){
setWage ( hourlyWage ) ; // valida a remuneracao por horas e t H o u r s ( hoursWorked ) ; // valida as horas trabalhadas
} // fim do construtor HourlyEmployee
87/104
HourlyEmployee.cpp (cont.)
// calcula os rendimentos;// sobrescreve a funcao virtual pura earnings em Employeed o u b l e Hour lyEmployee : : e a r n i n g s ( ) c o n s t{
i f ( getHours ( ) <= 40 ) // nenhuma hora extrar e t u r n getWage ( ) ∗ getHours ( ) ;
e l s er e t u r n 40 ∗ getWage ( ) + ( ( getHours ( ) − 40 ) ∗
getWage ( ) ∗ 1 . 5 ) ;} // fim da funcao earnings
88/104
HourlyEmployee.cpp (cont.)
// imprime informacoes do HourlyEmployeev o i d Hour lyEmployee : : p r i n t ( ) c o n s t{
cout << "hourly employee: " ;Employee : : p r i n t ( ) ; // reutilizacao de codigocout << "\nhourly wage: " << getWage ( )
<< "; hours worked: " << getHours ( ) ;} // fim da funcao print
89/104
SalariedEmployee.h
#i f n d e f SALARIED H#d e f i n e SALARIED H#i n c l u d e "Employee.h" // Definicao da classe Employeec l a s s S a l a r i e d E m p l o y e e : p u b l i c Employee{
d o u b l e w e e k l y S a l a r y ; // salario por semanap u b l i c :
S a l a r i e d E m p l o y e e ( c o n s t s t r i n g &="" , c o n s t s t r i n g &="" ,c o n s t s t r i n g &="" , d o u b l e = 0 . 0 ) ;
v o i d s e t W e e k l y S a l a r y ( d o u b l e ) ;d o u b l e g e t W e e k l y S a l a r y ( ) c o n s t ;
// palavra-chave virtual assinala intencao de sobrescreverv i r t u a l d o u b l e e a r n i n g s ( ) c o n s t ; // calcula os rendimentosv i r t u a l v o i d p r i n t ( ) c o n s t ; // imprime SalariedEmployee
} ; // fim da classe SalariedEmployee#e n d i f
90/104
SalariedEmployee.h
#i n c l u d e <i o s t r e a m>u s i n g s t d : : cout ;
#i n c l u d e "SalariedEmployee.h"
// construtorS a l a r i e d E m p l o y e e : : S a l a r i e d E m p l o y e e ( c o n s t s t r i n g &f i r s t ,
c o n s t s t r i n g &l a s t ,c o n s t s t r i n g &ssn ,d o u b l e s a l a r y )
: Employee ( f i r s t , l a s t , s s n ){
s e t W e e k l y S a l a r y ( s a l a r y ) ;} // fim do construtor SalariedEmployee
91/104
SalariedEmployee.h (cont.)
// calcula os rendimentos;// sobrescreve a funcao virtual pura earnings em Employeed o u b l e S a l a r i e d E m p l o y e e : : e a r n i n g s ( ) c o n s t{
r e t u r n g e t W e e k l y S a l a r y ( ) ;} // fim da funcao earnings
// imprime informacoes de SalariedEmployeev o i d S a l a r i e d E m p l o y e e : : p r i n t ( ) c o n s t{
cout << "salaried employee: " ;Employee : : p r i n t ( ) ;cout << "\nweekly salary: " << g e t W e e k l y S a l a r y ( ) ;
} // fim da funcao print
92/104
ComissionEmployee.h
#i f n d e f COMMISSION H#d e f i n e COMMISSION H#i n c l u d e "Employee.h" // Definicao da classe Employeec l a s s CommissionEmployee : p u b l i c Employee {
d o u b l e g r o s s S a l e s ; // vendas brutas semanaisd o u b l e commiss ionRate ; // porcentagem da comissao
p u b l i c :CommissionEmployee ( c o n s t s t r i n g &="" , c o n s t s t r i n g &="" ,
c o n s t s t r i n g &="" , d o u b l e = 0 . 0 , d o u b l e = 0 . 0 ) ;
v o i d setCommiss ionRate ( d o u b l e ) ;d o u b l e getCommiss ionRate ( ) c o n s t ;v o i d s e t G r o s s S a l e s ( d o u b l e ) ;d o u b l e g e t G r o s s S a l e s ( ) c o n s t ;// palavra-chave virtual assinala intencao de sobrescreverv i r t u a l d o u b l e e a r n i n g s ( ) c o n s t ; // calcula os rendimentosv i r t u a l v o i d p r i n t ( ) c o n s t ; // imprime o objeto CommissionEm-
ployee} ; // fim da classe CommissionEmployee
#e n d i f
93/104
ComissionEmployee.cpp
#i n c l u d e <i o s t r e a m>u s i n g s t d : : cout ;
#i n c l u d e "CommissionEmployee.h"
// construtorCommissionEmployee : : CommissionEmployee ( c o n s t s t r i n g &f i r s t ,
c o n s t s t r i n g &l a s t ,c o n s t s t r i n g &ssn ,d o u b l e s a l e s ,d o u b l e r a t e )
: Employee ( f i r s t , l a s t , s s n ){
s e t G r o s s S a l e s ( s a l e s ) ;se tCommiss ionRate ( r a t e ) ;
} // fim do construtor CommissionEmployee
94/104
ComissionEmployee.cpp (cont.)
// calcula os rendimentos;// sobrescreve a funcao virtual pura earnings em Employeed o u b l e CommissionEmployee : : e a r n i n g s ( ) c o n s t{
r e t u r n getCommiss ionRate ( ) ∗ g e t G r o s s S a l e s ( ) ;} // fim da funcao earnings
// imprime informacoes do CommissionEmployeev o i d CommissionEmployee : : p r i n t ( ) c o n s t{
cout << "commission employee: " ;Employee : : p r i n t ( ) ; // reutilizacao de codigocout << "\ngross sales: " << g e t G r o s s S a l e s ( )
<< "; commission rate: " << getCommiss ionRate ( ) ;} // fim da funcao print
95/104
BasePlusComissionEmployee.h
#i f n d e f BASEPLUS H#d e f i n e BASEPLUS H#i n c l u d e "CommissionEmployee.h"
c l a s s BasePlusCommiss ionEmployee :p u b l i c CommissionEmployee {
d o u b l e b a s e S a l a r y ; // salario-base por semanap u b l i c :
BasePlusCommiss ionEmployee ( c o n s t s t r i n g &="" ,c o n s t s t r i n g &="" , c o n s t s t r i n g &="" , d o u b l e = 0 . 0 ,d o u b l e = 0 . 0 , d o u b l e = 0 . 0 ) ;
v o i d s e t B a s e S a l a r y ( d o u b l e ) ; // configura o salario-based o u b l e g e t B a s e S a l a r y ( ) c o n s t ; // retorna o salario-base// palavra-chave virtual assinala intencao de sobrescreverv i r t u a l d o u b l e e a r n i n g s ( ) c o n s t ; // calcula os rendimentosv i r t u a l v o i d p r i n t ( ) c o n s t ; // imprime o objeto BasePlusCom-
missionEmployee} ; // fim da classe BasePlusCommissionEmployee
#e n d i f
96/104
BasePlusComissionEmployee.cpp
#i n c l u d e <i o s t r e a m>u s i n g s t d : : cout ;// Definicao da classe BasePlusCommissionEmployee#i n c l u d e "BasePlusCommissionEmployee.h"
// construtorBasePlusCommiss ionEmployee : : BasePlusCommiss ionEmployee (
c o n s t s t r i n g &f i r s t ,c o n s t s t r i n g &l a s t ,c o n s t s t r i n g &ssn ,d o u b l e s a l e s ,d o u b l e r a t e ,d o u b l e s a l a r y ): CommissionEmployee ( f i r s t , l a s t , ssn , s a l e s , r a t e )
{s e t B a s e S a l a r y ( s a l a r y ) ; // valida e armazena o salario-base
} // fim do construtor BasePlusCommissionEmployee
97/104
BasePlusComissionEmployee.cpp (cont.)
// calcula os rendimentos;// sobrescreve a funcao virtual pura earnings em Employeed o u b l e BasePlusCommiss ionEmployee : : e a r n i n g s ( ) c o n s t{
r e t u r n g e t B a s e S a l a r y ( ) +CommissionEmployee : : e a r n i n g s ( ) ;
} // fim da funcao earnings
// imprime informacoes de BasePlusCommissionEmployeev o i d BasePlusCommiss ionEmployee : : p r i n t ( ) c o n s t{
cout << "base -salaried " ;CommissionEmployee : : p r i n t ( ) ; // reutilizacao de codigocout << "; base salary: " << g e t B a s e S a l a r y ( ) ;
} // fim da funcao print
98/104
Main.cpp
#i n c l u d e <i o s t r e a m>#i n c l u d e <iomanip>u s i n g namespace s t d ;
#i n c l u d e <v e c t o r>// inclui definicoes de classes na hierarquia Employee#i n c l u d e "Employee.h"
#i n c l u d e "SalariedEmployee.h"
#i n c l u d e "HourlyEmployee.h"
#i n c l u d e "CommissionEmployee.h"
#i n c l u d e "BasePlusCommissionEmployee.h"
v o i d v i r t u a l V i a P o i n t e r ( c o n s t Employee∗ c o n s t ) ; // prototipov o i d v i r t u a l V i a R e f e r e n c e ( c o n s t Employee &); // prototipo
99/104
Main.cpp (cont.)
i n t main ( ){
// configura a formatacao de saıda de ponto flutuantecout << f i x e d << s e t p r e c i s i o n ( 2 ) ;
// cria objetos da classe derivadaS a l a r i e d E m p l o y e e s a l a r i e d E m p l o y e e (
"John" , "Smith" , "111-11-1111" , 800 ) ;Hour lyEmployee h o u r l y E m p l o y e e (
"Karen" , "Price" , "222-22-2222" , 1 6 . 7 5 , 40 ) ;CommissionEmployee commiss ionEmployee (
"Sue" , "Jones" , "333-33-3333" , 10000 , . 0 6 ) ;BasePlusCommiss ionEmployee basePlusCommiss ionEmployee (
"Bob" , "Lewis" , "444-44-4444" , 5000 , . 0 4 , 300 ) ;. . .
100/104
Main.cpp (cont.)
cout << "Employees processed individually using
static binding:\n\n" ;
// saıda de info. e rendimentos dos Employees com vinculacao estaticas a l a r i e d E m p l o y e e . p r i n t ( ) ;cout << "\nearned $" << s a l a r i e d E m p l o y e e . e a r n i n g s ( ) ;h o u r l y E m p l o y e e . p r i n t ( ) ;cout << "\nearned $" << h o u r l y E m p l o y e e . e a r n i n g s ( ) ;commiss ionEmployee . p r i n t ( ) ;cout << "\nearned $" << commiss ionEmployee . e a r n i n g s ( ) ;basePlusCommiss ionEmployee . p r i n t ( ) ;cout << "\nearned $" ’
<< basePlusCommissionEmployee.earnings();
101/104
Main.cpp (cont.)
// cria um vector a partir dos quatro ponteiros da classe basicav e c t o r < Employee ∗ > employees ( 4 ) ;
// inicializa o vector com Employeesemployees [ 0 ] = &s a l a r i e d E m p l o y e e ;employees [ 1 ] = &h o u r l y E m p l o y e e ;employees [ 2 ] = &commiss ionEmployee ;employees [ 3 ] = &basePlusCommiss ionEmployee ;
cout << "Employees processed polymorphically via
dynamic binding:\n\n" ;
102/104
Main.cpp (cont.)
// chama virtualViaPointer para imprimir informacoes e rendimentos// de cada Employee utilizando vinculacao dinamicacout << "Virtual function calls made off
base -class pointers:\n\n" ;
f o r ( s i z e t i = 0 ; i < employees . s i z e ( ) ; i++ )v i r t u a l V i a P o i n t e r ( employees [ i ] ) ;
// chama virtualViaReference para imprimir informacoes// de cada Employee utilizando vinculacao dinamicacout << "Virtual function calls made off base -class
references:\n\n" ;
f o r ( s i z e t i = 0 ; i < employees . s i z e ( ) ; i++ )// observe o desreferenciamento
v i r t u a l V i a R e f e r e n c e ( ∗ employees [ i ] ) ;
r e t u r n 0 ;} // fim de main
103/104
Main.cpp (cont.)
// chama funcoes print e earnings virtual de Employee a partir de um// ponteiro de classe basica utilizando vinculacao dinamicav o i d v i r t u a l V i a P o i n t e r ( c o n s t Employee∗ c o n s t b a s e C l a s s P t r ){
b a s e C l a s s P t r−>p r i n t ( ) ;cout << "\nearned $" << b a s e C l a s s P t r−>e a r n i n g s ( ) ;
} // fim da funcao virtualViaPointer
// chama funcoes print e earnings virtual de Employee a partir de um// referencia de classe basica utilizando vinculacao dinamicav o i d v i r t u a l V i a R e f e r e n c e ( c o n s t Employee &b a s e C l a s s R e f ){
b a s e C l a s s R e f . p r i n t ( ) ;cout << "\nearned $" << b a s e C l a s s R e f . e a r n i n g s ( ) ;
} // fim da funcao virtualViaReference
104/104
FIM