Buscar

Programação Orientada a Objetos - Poli 2016 - C++ - Aula06 Herança e Polimorfismo I

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 3, do total de 68 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 6, do total de 68 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 9, do total de 68 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Prévia do material em texto

Escola Politécnica da Universidade de São Paulo Escola Politécnica da Universidade de São Paulo 
Laboratório de Programação 
Orientada a Objetos para 
Engenharia Elétrica 
Aula 6: Herança e Polimorfismo I 
PCS3111 
Agenda 
1.  Herança 
2.  Modo Protegido 
3.  Polimorfismo 
4.  Princípio da Substituição 
5.  Casting 
2 
Agenda 
1.  Herança 
2.  Modo Protegido 
3.  Polimorfismo 
4.  Princípio da Substituição 
5.  Casting 
3 
Herança em OO 
!  Herança é uma das características essenciais 
da Orientação a Objetos! 
!  Em um domínio, é comum que as classes 
tenham características semelhantes. 
!  O termo expressa a transmissão de 
características, como na herança genética: 
4 
Avó e neta Pai e filha Tarcísio-pai e Tarcísio Filho 
Herança (Inheritance) 
!  Herança é o processo pelo qual uma nova classe, 
denominada classe derivada, é criada a partir de 
uma classe já existente, chamada de classe base. 
!  A nova classe derivada “pega emprestado” o 
comportamento da classe base. 
!  A nova classe derivada é chamada de subclasse. 
 
!  A classe base original é chamada de 
superclasse. 
5 
Nomenclatura 
São equivalentes os seguintes pares: 
 
Classe base e classe derivada 
ou 
Classe mãe e classe filha 
(obs: classe ancestral se refere a qualquer nível de herança) 
ou 
Superclasse e subclasse 
6 
A subclasse herda o comportamento da 
superclasse 
 
Todos os membros (atributos e métodos) da 
superclasse são comuns a todas as subclasses 
dela derivadas. 
 
A derivação não altera a classe base, isto é, a 
classe base preserva seus métodos e atributos. 
 
 
7 
Herança 
Ao se criar uma classe B, 
 
!  Se já existir uma classe A 
que representa um conceito 
mais geral 
!  Se a classe B é um tipo de 
A e, por isso, possui os 
mesmos atributos e métodos, 
Então, nesse caso, pode-se 
definir a classe B como uma 
classe derivada da classe A. 
 
A classe A será a superclasse 
de B. 
8 
A	
B	
Subclasse 
Superclasse 
A subclasse pode adicionar seu 
comportamento específico 
!  Subclasses também podem adicionar seus 
próprios atributos e métodos: 
•  A classe B pode ter atributos próprios, além dos 
atributos de A. 
•  A classe B pode ter métodos próprios, além dos 
métodos de A. 
9 
Exemplo 
10 
Todos os atributos e 
métodos de Empregado se 
transmitem por herança a 
Pesquisador e Vendedor. 
Vendedor é um tipo de 
Empregado. Além de nome e 
salario, ele é caracterizado 
pela comissao. 
Pesquisador é um tipo de Empregado. 
Além de nome e salario, ele é 
caracterizado pelo numeroDeArtigos. 
Todas as classes da hierarquia podem 
ter instâncias! (Por enquanto...) 
No exemplo: 
11 
Manoela é uma 
instância de 
Pesquisador	
Otávio é uma 
instância de 
Vendedor	
Ana é uma 
instância de 
Empregado 
(i.e., não é nem 
pesquisadora nem 
vendedora!) 
Por que usar herança? 
!  Porque o mecanismo de herança possibilita o 
reuso de código: 
•  Com a derivação de uma classe a partir de outra, 
atributos e métodos são herdados: não precisam ser 
reescritos! (Mas podem, como vamos ver) 
•  Se muitos desenvolvedores usam a mesma classe, 
aumenta a chance de descobrirem erros => maior 
confiabilidade do código. 
!  Porque com herança podemos organizar o 
projeto em hierarquias, tornando o código mais 
inteligível. 
12 
Vantagens e desvantagens da herança 
!  Vantagem: diminuição de esforço de 
programação e depuração: 
•  Pode-se evoluir um projeto que tenha 
código já testado e em funcionamento, ao 
invés de fazer código novo. 
•  Nem sempre se tem acesso ao código da 
classe base, mas isso não impede de criar 
uma classe derivada a partir dela! 
 
!  Desvantagens 
•  Velocidade de execução 
•  Complexidade estrutural do código 
13 
Generalizar x especializar 
A herança é usada num projeto em duas situações: 
!  Especialização: quando se deseja criar um 
comportamento especial a partir do mais geral. 
•  Ex.: um ExameDeGlicemia é um tipo de ExameDeSangue, 
com características específicas. 
!  Generalização: quando existe um comportamento 
comum a várias classes, e torna-se interessante ter 
uma classe base, eliminando redundâncias. 
•  Ex.: tanto os exames de sangue quanto os de imagem 
estão associados a um médico e um paciente. Fica mais 
claro ter uma classe Exame, que se associa a Médico e 
Paciente, porque ExamesDeSangue e ExamesDeImagem 
são tipos de Exame. 
14 
Não confundir herança com composição! 
Tanto na herança e na composição, as 
classes se estruturam numa hierarquia! 
 
A composição é uma 
relação entre todo e partes 
Por exemplo, um ventilador 
é composto de motor, pás e 
grade. 
A herança é uma relação entre 
tipos. 
Por exemplo, há diferentes tipos 
de ventilador: de mesa, de 
parede, de pé. 
15 
Como declarar subclasses em C++ 
16 
class	NomeSuperClasse	{	
//	atributos	da	classe	
		
public:	
		//	métodos	da	classe	
};	
		
	
	
class	NomeSubClasse:	public	NomeSuperClasse	{	
//	novos	atributos	da	subclasse	
		
public:	
//	novos	métodos	da	subclasse	
};	
indica herança 
Agenda 
1.  Herança 
2.  Modo Protegido 
3.  Polimorfismo 
4.  Princípio da Substituição 
5.  Casting 
17 
Acesso aos membros da classe base 
!  Os métodos de uma classe sempre podem 
acessar os atributos e métodos desta classe, 
independente se declarados públicos ou 
privados. 
!  Já os objetos externos da classe só podem 
acessar os membros públicos da classe. 
!  Quais membros da classe base podem ser 
usados pela classe derivada desta classe base? 
!  Depende... 
18 
Controle de acesso 
!  Escopo Privado (private) 
•  Nomes podem ser usados apenas nos métodos 
próprios da classe. 
!  Escopo Protegido (protected) 
•  Nomes podem ser usados em métodos próprios e de 
classes (tipos) derivadas. 
!  Escopo Público (public) 
•  Nomes podem ser usados em quaisquer métodos. 
19 
Acesso aos membros da classe 
20 
class	NomeSuperClasse	{	
private:	//	acessíveis	só	aos	objetos	desta	classe	
					
protected:	//	acessíveis	às	subclasses	
					
public:	//acessíveis	às	classes	externas	à	hierarquia	
};	
		
	
class	NomeSubClasse:	public	NomeSuperClasse	{	
private:	//	acessíveis	só	aos	objetos	desta	classe	
					
protected:	//	acessíveis	às	subclasses	
					
public:	//acessìveis	às	classes	externas	à	hierarquia	
};	
Atributos Protegidos na Superclasse 
Exemplo 1 
Membros protegidos são acessíveis aos objetos 
das subclasses 
21 
Notação: 
 
# Elemento protegido 
+ Elemento público 
Classe Empregado (.h) 
22 
18		class	Empregado	{	
19		protected:	
20				string	nome	;	
21				double	salario;	
22			
23		public:	
24				Empregado	(string	nome);	
25				~Empregado	();	
26			
27				string	getNome();	
28				void	setNome	(string	nome);	
29				double	getSalario();	
30				void	setSalario	(double	salario);	
31			
32				double	calcularSalarioLiquido();	
33		};	
Atributos podem ser 
acessados por objetos das 
subclasses 
No exemplo: 
!  Todo Empregado recebe um salário padrão de 
R$ 5.000,00 
!  Um Pesquisador recebe um adicional de salário, 
por ser pesquisador, de R$1.000,00 
!  Todos os empregados têm desconto de 15% de 
IRPF. 
23 
Classe Empregado (.cpp) 
24 
14		double	const	salarioPadrao	=	5000.;	
15			
16		Empregado::Empregado	(string	nome)	{	
17				this->setNome	(nome);	
18				this->setSalario	(	
20						salarioPadrao);	//	salário	padrão	da	empresa	
21		}	
22			
23		Empregado::~Empregado	()	{	
24				cout	<<	"Empregado	removido"	<<	endl;	
25		}	
26			
27		string	Empregado::getNome	()	{	
28				return	nome;	
29		}	
30			
Classe Empregado (.cpp) 
2531		void	Empregado::setNome	(string	nome)	{	
32				this->nome	=	nome;	
33		}	
34			
35		void	Empregado::setSalario	(double	salario)	{	
36				this->salario	=	salario;	
37		}	
38			
39		double	Empregado::getSalario()	{	
40				return	this->salario;	
41		}	
42		double	Empregado::calcularSalarioLiquido	()	{	
43				//	desconto	do	irpf	
44				return	this->getSalario()	*	0.85;	
45		}	
46			
Subclasse Pesquisador (.h) 
26 
14		#include	"Empregado.h"	
15			
16		using	namespace	std;	
17			
18		class	Pesquisador	:	public	Empregado	{	
19		private:	
20				int	numeroDeArtigos;	
21			
22		public:	
23				Pesquisador	(string	nome,	int	numeroDeArtigos);	
24				~Pesquisador	();	
25			
26				int	getNumeroDeArtigos();	
27				void	setNumeroDeArtigos	(int	numeroDeArtigos);	
28			
29		};	
30			
Subclasse 
getNome() não é redeclarado. 
Usa-se o método da superclasse (herança). 
Antes de rodar o programa, vamos ver 
os construtores e destrutores das 
subclasses 
27 
Construtores das subclasses 
!  Um objeto da subclasse é também um objeto da superclasse! 
!  Para construir o objeto da subclasse, deve-se chamar o 
construtor da superclasse no construtor da subclasse. 
!  Se não chamar, o compilador usará automaticamente o 
construtor padrão da superclasse. 
!  Se a superclasse não tiver construtor (isto é, usar o construtor 
padrão), naturalmente, será usado o construtor padrão da 
superclasse. 
 
 
28 
Subclasse::Subclasse	(<params>)	:	SuperClasse	(<args>)	
14		Pesquisador::Pesquisador	(string	nome,	
15																										int	numeroDeArtigos)	:	Empregado	(nome)	
Destrutores das subclasses 
!  Como o objeto da subclasse é também um 
objeto da superclasse, é necessário destruir não 
só o objeto da subclasse, mas também o objeto 
da superclasse! 
 
29 
Subclasse Pesquisador (.cpp) 
30 
10		#include	"Pesquisador.h"	
11			
12		double	const	adicionalPesquisador	=	1000.0;	
13			
14		Pesquisador::Pesquisador	(string	nome,	
15																												int	numeroDeArtigos)	:	Empregado	
(nome)	{	
16				this->numeroDeArtigos	=	numeroDeArtigos;	
17				this->salario	=	this->salario	+	adicionalPesquisador;	
18		}	
19			
20		Pesquisador::~Pesquisador	()	{	
21				cout	<<	"Pesquisador	removido"	<<	endl;	
22		}	
23			
24		int	Pesquisador::getNumeroDeArtigos	()	{	
25				return	this->numeroDeArtigos;	
26	}	
Chamando o 
construtor da 
superclasse 
salario é protected	
Herança de métodos 
31 
Herança de métodos 
!  Assim como os atributos, os métodos da 
superclasse são herdados pelas subclasses. 
!  Seja f um método na superclasse A (A::f()). 
Na subclasse B, há três alternativas: 
1.  Herdar o método f exatamente como definido na 
superclasse, simplesmente não declarando f na 
subclasse. 
2.  Estender f fornecendo uma nova implementação 
para f na subclasse B que chama a função f 
definida em A (A::f()). 
3.  Substituir f da superclasse, fornecendo uma nova 
implementação na subclasse B, não relacionada à 
implementação original. 
32 
Alternativa 1. herdar o método f 
exatamente como definido na superclasse 
33 
Por exemplo, getNome()	
na classe Empregado é 
herdado pelas subclasses 
Pesquisador e Vendedor	
Exemplo 1 
34 
	9		#include	"Empregado.h"	
10		#include	"Pesquisador.h"	
11		#include	"Vendedor.h"	
12			
13		int	main	(int	argc,	char**	argv)	{	
14				Empregado	*e	=	new	Empregado	("Ana");	
15				Pesquisador	*p	=	new	Pesquisador	("Manoela",	2);	
16				Vendedor	*v	=	new	Vendedor	("Otavio",	500.);	
17				//	mostra	o	nome	de	cada	empregado	
18				cout	<<	"Empregado:	"	<<	e->getNome()	<<	endl;	
19				cout	<<	"Pesquisador:	"	<<	p->getNome()	<<	endl;	
20				cout	<<	"Vendedor:	"	<<	v->getNome()	<<	endl;	
21				delete	e;	
22				delete	p;	
23				delete	v;	
24		}	 getNome()	 na classe Empregado é herdado 
pelas subclasses Pesquisador e Vendedor	
Observe, neste exemplo, que: 
!  Na construção das instâncias das três classes, o 
atributo nome foi definido pelo construtor da 
superclasse. 
!  No main, o método getNome foi invocado a 
partir de objetos das subclasses. 
!  O destrutor da superclasse foi chamado ao se 
destruir o objeto da subclasse. 
35 
Alternativa 2. Estender o método da 
superclasse 
36 
O método calcularSalarioLiquido() é 
estendido na subclasse Vendedor	
Neste caso, estende-se 
f fornecendo uma nova 
implementação para f 
na subclasse B que 
chama a função f 
definida em A	
(A::f()) 
Exemplo 2 
!  Suponha que o vendedor receba uma comissão 
acrescida ao seu salário base, isenta de IRPF. 
37 
18		class	Vendedor	:	public	Empregado	{	
19		private:	
20				double	comissao;	
21			
22		public:	
23				Vendedor	(string	nome,	double	comissao);	
24				~Vendedor	();	
25			
26				double	getComissao();	
27				void	setComissao	(double	comissao);	
28	
29				double	calcularSalarioLiquido();	
30		};	
31			 vendedor.h 
Cálculo do salário do vendedor 
 
38 vendedor.cpp 
12		Vendedor::Vendedor	(string	nome,	
13																						double	comissao)	:	Empregado	(nome)	{	
14				this->setComissao	(comissao);	
15		}	
16			
17		Vendedor::	~Vendedor	()	{	
18		}	
19			
20		double	Vendedor::getComissao()	{	
21				return	this->comissao;	
22		}	
23			
24		void	Vendedor::setComissao	(double	comissao)	{	
25				this->comissao	=	comissao;	
26		}	
27			
28		double	Vendedor::calcularSalarioLiquido()	{	
29				return	(Empregado::calcularSalarioLiquido()	+	
30												this->getComissao()	);	
31		}	
O método 
calcularSalarioLiquido() de 
Empregado é usado na subclasse. 
39 
13		int	main	(int	argc,	char**	argv)	{	
14			
15				double	comissao;	
16			
17				cout	<<	"Entre	a	comissao	do	vendedor:	"	<<	endl;	
18				cin	>>	comissao;	
19			
20				Empregado	*e	=	new	Empregado	("Ana");	
21				Vendedor	*v	=	new	Vendedor	("Otavio",	comissao);	
22			
23				cout	<<	"Empregado:	"	<<	e->getNome()	<<	endl;	
24				cout	<<	"Salario	liquido	=	"	<<	e->calcularSalarioLiquido()	<<	
25									endl	<<	endl;	
26				cout	<<	"Vendedor:	"	<<	v->getNome()	<<	endl;	
27				cout	<<	"Salario	liquido	=	"	<<	v->calcularSalarioLiquido()	<<	
28									endl	<<	endl;	
29			
30				delete	e;	
31				delete	v;	
32		}	
33			
main.cpp 
Observe, neste exemplo: 
!  O método getSalarioLiquido() foi declarado 
em Vendedor	
!  Por isso, na classe Vendedor.cpp o método é 
definido. 
!  Na definição, para usar o método da 
superclasse tivemos que usar o operador de 
resolução de escopo. 
!  Por quê? O que aconteceria se não tivéssemos 
usado? Experimente!!!! 
40 
Caso 3. Dar uma nova implementação 
para o método da superclasse 
Neste caso, f na subclasse B é independente de 
f definida em A	
41 
O método 
calcularSalarioLiquido() 
é redefinido na subclasse 
Pesquisador. 
!  Suponha que o salário do pesquisador seja 
incrementado com um bônus proporcional ao número de 
artigos publicados, incidindo IRPF sobre o total. 
18		class	Pesquisador	:	public	Empregado	{	
19		private:	
20				int	numeroArtigos;	
21			
22		public:	
23				Pesquisador	(string	nome,	int	numeroDeArtigos);	
24				~Pesquisador	();	
25			
26				int	getNumeroDeArtigos();	
27				void	setNumeroDeArtigos	(int	numeroDeArtigos);	
28			
29				double	calcularSalarioLiquido();	
30			
31		};	
Exemplo 3 
42 
pesquisador.h 
12		double	const	adicionalPesquisador	=	1000.0,	bonus	=	300;	
13			
14		Pesquisador::Pesquisador	(string	nome,	
15																												int	numeroDeArtigos)	:	Empregado	(nome)	{	
16				this->numeroDeArtigos	=	numeroDeArtigos;	
17				this->salario	=	this->salario	+	adicionalPesquisador;	
18		}	
19			
20		Pesquisador::~Pesquisador()	{	
21				cout	<<	"Pesquisador	removido"	<<	endl;	
22		}	
23			
24		int	Pesquisador::getNumeroDeArtigos()	{	
25return	this->numeroDeArtigos;	
26		}	
27			
28		void	Pesquisador::setNumeroDeArtigos	(int	numeroDeArtigos)	{	
29				this->numeroDeArtigos	=	numeroDeArtigos;	
30		}	
31			
32		double	Pesquisador::calculaSalarioLiquido()	{	
33				return	(this->salario	+	(this->getNumeroDeArtigos()	*	bonus)	*	
34												0.85);	
35		}	
43 
pesquisador.cpp 
44 
main.cpp 
13		int	main	(int	argc,	char**	argv)	{	
14			
15				Pesquisador	*p	=	new	Pesquisador	("Manoela",	3);	
16			
17				cout	<<	"Pesquisadora:	"	<<	p->getNome()	<<	endl;	
18				cout	<<	"Salario	liquido	=	"	<<	p->calcularSalarioLiquido()	<<	
19									endl	<<	endl;	
20			
21				delete	p;	
22		}	
!  A implementação de getSalarioLiquido() da 
subclasse Pesquisador é completamente 
independente da implementação da superclasse 
Empregado. 
!  Existe uma implementação específica do 
destrutor da classe Pesquisador mas mesmo 
assim, o destrutor da superclasse é acionado! 
Observe, neste exemplo, que: 
45 
!  Membros privados não são acessíveis aos 
objetos das subclasses! 
!  Exemplo 4: Se a declaração de Empregado for: 
Atributos Privados na Superclasse 
18		class	Empregado	{	
19		private:	
20				string	nome	;	
21				double	salario;	
22			
23		public:	
...	
46 
In	constructor	'Pesquisador::Pesquisador(std::string,	int)':|	
include\Empregado.h|21|error:	'double	Empregado::salario'	is	private|	
A compilação resultará em 
Atributos Privados na Superclasse 
Para aumentar o desacoplamento, declaram-se atributos como 
private e se usam os métodos de acesso nas classes derivadas! 
47 
18		class	Empregado	{	
19		private:	
20				string	nome	;	
21				double	salario;	
22			
23		public:	
24				Empregado	(string	nome);	
25				~Empregado	();	
26			
27				string	getNome();	
28				void	setNome	(string	nome);	
29				double	getSalario();	
30				void	setSalario	(double	salario);	
31			
32				double	calcularSalarioLiquido();	
33		};	
Para acessar os 
atributos privados 
empregado.h 
Exemplo 4 
!  Os métodos de Pesquisador ficam: 
48 
13		double	const	adicionalPesquisador	=	1000.0,	bonus	=	300;	
14			
15		Pesquisador::Pesquisador	(string	nome,	
16																												int	numeroDeArtigos)	:	Empregado	(nome)	{	
17				this->numeroDeArtigos	=	numeroDeArtigos;	
18				this->setSalario	(Empregado::getSalario()	+	
19																						adicionalPesquisador);	
20		}	
21			
...	
	
34		double	Pesquisador::calcularSalarioLiquido()	{	
35				return	(	(this->getSalario()	+	(this->getNumeroDeArtigos()	*	
36																																				bonus)	)	*	0.85);	
37		}	
Agenda 
1.  Herança 
2.  Modo Protegido 
3.  Polimorfismo 
4.  Princípio da Substituição 
5.  Casting 
49 
Polimorfismo 
!  Polimorfismo é o nome que se dá à propriedade 
de um mesmo nome ter diferentes significados. 
!  Nos exemplos, o método getSalarioLiquido é 
polimórfico, porque há diferentes 
implementações para o mesmo nome. 
!  O compilador precisa resolver qual o método 
mais adequado para cada momento. 
!  Esse assunto será tratado com rigor na próxima 
aula! 
50 
Agenda 
1.  Herança 
2.  Modo Protegido 
3.  Polimorfismo 
4.  Princípio da Substituição 
5.  Casting 
51 
Princípio da substituição de Liskov 
“ Se S é um subtipo declarado de T, objetos do tipo 
S devem se comportar como se espera que 
objetos de T se comportem, se forem tratados 
como objetos do tipo T. ” 
52 
O que isso significa? 
!  Que em todos os contextos em que um objeto 
de T for requerido, um objeto de S é admitido. 
!  Que as funções que usam ponteiros ou 
referências a objetos de T podem usar objetos 
de S sem qualquer modificação. 
!  Por isso, podemos fazer: 
Empregado	*p	=	new	Pesquisador	("Manoela",	3);	
53 
Exemplo 5 
!  Suponha que precisemos de uma aplicação que 
cadastre os empregados contratados pela empresa, 
mantendo uma lista de empregados 
!  Só vamos saber o tipo de cada empregado durante 
a execução do programa. 
!  Podemos fazer uma listaDeEmpregados como 
uma lista de ponteiros para Empregado, 
independente de qual o tipo de empregado. 
!  Pelo princípio da substituição, onde se pede um 
objeto do tipo Empregado pode-se usar um objeto 
de uma de suas subclasses. 
54 
55 
14		int	main	(int	argc,	char**	argv)	{	
15			
16				Empregado	*listaDeEmpregados	[10];	
17				int	numeroDeEmpregados	=	0;	
18				int	tipoDeEmpregado;	
19				int	numeroDeArtigos	=	0;	
20				double	comissao	=	0.;	
21				string	nome;	
22				bool	sair	=	false;	
23			
24				while	(!sair)		{	
25						cout	<<	"Informe	tipo:	1	para	Empregado,	2	para	Pesquisador,	3	
para	Vendedor,	outro	para	sair"	
26											<<	endl;	
27						cin	>>		tipoDeEmpregado;	
28			
29						switch	(tipoDeEmpregado)	{	
30						case	1:	
31								cout	<<	"nome	do	Empregado:	";	
32								cin	>>	nome;	
33								listaDeEmpregados	[numeroDeEmpregados]	=	new	Empregado	(nome);	
34								break;	
35			
36						case	2:	
37								cout	<<	"nome	do	Pesquisador:	";	
38								cin	>>	nome;	
39								listaDeEmpregados	[numeroDeEmpregados]	=	new	Pesquisador	(nome,	
40												numeroDeArtigos);	
41								break;	
42			
43						case	3:	
44								cout	<<	"nome	do	Vendedor:	";	
45								cin	>>		nome;	
46								listaEmpregados	[numeroDeEmpregados]	=	new	Vendedor	(nome,	
47												comissao);	
48								break;	
49			
50						default:	
51								sair	=	true;	
52								break;	
53						}	
54			
55						//	incrementa	o	número	de	empregados	na	lista	
56						numeroDeEmpregados++;	
57				}	 56 
29						switch	(tipoDeEmpregado)	{	
30						case	1:	
31								cout	<<	"nome	do	Empregado:	";	
32								cin	>>	nome;	
33								listaDeEmpregados	[numeroDeEmpregados]	=	new	Empregado	(nome);	
34								break;	
35			
36						case	2:	
37								cout	<<	"nome	do	Pesquisador:	";	
38								cin	>>	nome;	
39								listaDeEmpregados	[numeroDeEmpregados]	=	new	Pesquisador	(nome,	
40												numeroDeArtigos);	
41								break;	
42			
43						case	3:	
44								cout	<<	"nome	do	Vendedor:	";	
45								cin	>>		nome;	
46								listaEmpregados	[numeroDeEmpregados]	=	new	Vendedor	(nome,	
47												comissao);	
48								break;	
49			
50						default:	
51								sair	=	true;	
52								break;	
53						}	
54			
55						//	incrementa	o	número	de	empregados	na	lista	
56						numeroDeEmpregados++;	
57				}	 57 
58 
59		//	imprime	o	nome	de	cada	empregado	
60				cout	<<	endl	<<	"Imprimindo	a	lista	de	empregados..."	<<	
61									endl;	
62			
63				for	(int	i	=	0;	i	<	(numeroDeEmpregados	-	1);	i++)	{	
64						cout	<<	listaDeEmpregados[i]->getNome()	<<	endl;	
65			
66				}	
67		}	
Observe, neste exemplo, que: 
!  Não sabemos, a priori, qual o tipo de Empregado 
que será criado. 
!  listaDeEmpregados é uma lista de ponteiros 
para Empregados. No entanto, ela pode receber 
ponteiros para as subclasses de Empregado. 
59 
Exemplo 6 
O que aconteceria se... 
!  ... quiséssemos imprimir também o salário de 
cada Empregado? 
!  Neste caso, o método 
calcularSalarioLiquido é diferente para 
cada subclasse. 
 
60 
61 
59		//	imprime	o	nome	de	cada	empregado	
60				cout	<<	endl	<<	"Imprimindo	a	lista	de	empregados..."	<<	
61									endl;	
62			
63				for	(int	i	=	0;	i	<	(numeroDeEmpregados	-	1);	i++)	{	
64						cout	<<	"O	salario	de	"	<<	listaDeEmpregados[i]->getNome()	<<	
65											"	e	R$"	<<	listaDeEmpregados[i]->calcularSalarioLiquido()	<<	
66											endl;	
67				}	
68		}	
O que houve com o 
salário líquido do 
vendedor Riquinho??? 
Agenda 
1.  Herança 
2.  Modo Protegido 
3.  Polimorfismo 
4.  Princípio da Substituição 
5.  Casting 
62 
Casting 
63 
Casting 
!  É a conversão de tipos controlada pelo 
desenvolvedor. 
!  Em C++•  Conversão de C 
!  (tipo) valor: 
•  int	a	=	(int)	b;	//	b	é	do	tipo	float.	
•  Conversão estática (tipos relacionados) 
!  static_cast<tipo>(valor) Inseguro (unsafe) 
•  Conversão dinâmica 
!  dynamic_cast<tipo>(valor) Seguro (safe) 
64 
Casting em hierarquia de tipos 
!  Upcasting: Tipos genéricos (acima, na 
hierarquia) sempre podem receber objetos de 
suas subclasses. 
•  Há garantia que subclasses possuem pelo menos os 
mesmos métodos que a classe base (Princípio da 
substituição). 
!  Downcasting: Tipos específicos (abaixo, na 
hierarquia) não podem receber explicitamente 
objetos que foram declarados como referências 
de suas superclasses. 
•  É preciso converter a referência. 
65 
Casting em hierarquia de tipos 
!  Casting estático: 
•  refFilha	=	static_cast<Filha	*>(refPai);	
!  O código acima funciona mas não é exatamente 
o que queremos. Pode resultar em problemas 
depois. 
66 
1		Empregado*	e	=	new	Vendedor	("João“,	300);	
2		Pesquisador*	p	=	e;				//	Erro,	“e”	não	é	do	tipo	esperado	
3			
4		Pesquisador*	p	=	static_cast<Pesquisador	*>(e);			//	Ok!	
5		int	numeroDeArtigos	=	p->getNumeroDeArtigos();	
Cast 
(unsafe) 
	1		double	calcularSalarioLiquido(Empregado*	e)	{	
	2				if	(Pesquisador*	p	=	dynamic_cast<Pesquisador	*>(e))	{	
	3						return	p->calcularSalarioLiquido	();	
	4				}	else	if	(Vendedor*	v	=	dynamic_cast<Vendedor	*>(e))	{	
	5						return	v->calcularSalarioLiquido	();	
	6				}	else	{	
	7						return	e->calcularSalarioLiquido	();	
	8				}	
	9		}	
Casting em hierarquia de tipos 
!  Casting dinâmico: 
•  if	(refFilha	=	dynamic_cast<Filha	*>(refPai))	{	...	};	
67 
Cast 
(safe) 
Bibliografia 
!  Budd, T. An Introduction to Object-Oriented 
Programming. Addison-Wesley, 3rd ed. 2002. 
!  Lafore, Robert. Object Oriented Programming in 
C++. Sams, 2002. 
!  Savitch, W. C++ Absoluto. Pearson, 1st ed. 
2003. 
 
68

Outros materiais