Buscar

Programação Orientada a Objetos - Poli 2016 - C++ - Aula05 Contrutores e Destrutores

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 5: Construtores e Destrutores 
PCS3111 
Agenda 
1.  Construtores 
2.  Destrutores 
3.  Escopo e gerenciamento de memória 
4.  Constantes 
 
2 
Agenda 
1.  Construtores 
2.  Destrutores 
3.  Escopo e gerenciamento de memória 
4.  Constantes 
3 
Construtores 
!  Em qualquer linguagem de programação, quando 
se deseja utilizar uma variável num programa deve-
se realizar ao menos duas operações: 
•  Criação da variável: alocação de espaço na memória e 
ligação deste espaço a um nome 
•  Inicialização da variável: colocar os valores iniciais e 
assegurar as condições iniciais necessárias para sua 
correta utilização 
!  Em POO, estas operações às vezes são mais 
complexas, pois temos que criar e inicializar objetos! 
!  Encapsulamento permite “esconder” estas 
operações do usuário do objeto. 
4 
Construtores 
!  Usualmente, na maioria das linguagens de 
programação, a criação se dá através de um 
comando de declaração 
 
!  Já a inicialização se dá num ou mais comando(s) 
de atribuição 
 
!  Problemas ocorrem se o usuário esquece de 
inicializar uma variável (ou se o faz mais de uma 
vez) 
 
5 
maximo	=	10;	
Inicialização 
int	maximo;	
Criação 
while	(i	<	maximo)	{...}	
Construtores 
!  É um método chamado automaticamente 
quando o objeto é criado, e contém as 
instruções para a sua correta inicialização 
•  Inicializar atributos com os valores adequados 
•  Eventualmente, criar objetos internos ... 
!  Com isto, se garante que um objeto nunca será 
utilizado sem que esteja pronto para tal 
!  Do ponto de vista da linguagem, trata-se de um 
método como outro qualquer, com algumas 
singularidades 
6 
Construtores em C++ 
!  Declaração do construtor 
•  Método tem o mesmo nome da classe 
•  Método não tem retorno 
•  Método pode ter parâmetros 
7 
1		class	Sensor	{	
2		public:	
3				int	numero;	
4				Residencia	*residencia;	
5			
6				Sensor	(int	numero,	Residencia	*residencia);	
7				void	detectarAcao();	
8		};	
Construtor 
Construtores em C++ 
 
 
 
 
 
!  Ocorre aqui uma situação interessante. Para ser 
mais legível, os parâmetros para inicialização 
têm os mesmos nomes dos atributos do objeto. 
Mas quando se deseja implementar o construtor, 
como se pode diferenciá-los? 
8 
1		class	Sensor	{	
2		public:	
3				int	numero;	
4				Residencia	*residencia;	
5			
6				Sensor	(int	numero,	Residencia	*residencia);	
7				void	detectarAcao();	
8		};	
Construtor 
Construtores em C++ 
!  Geralmente, na maioria das linguagens OO, o 
recipiente da mensagem não aparece 
explicitamente na chamada do método 
!  Quando se necessita acessar o recipiente de 
uma mensagem em um método, utiliza-se uma 
pseudo-variável 
•  Trata-se de uma variável que não necessita ser 
declarada e cujo valor não pode ser alterado 
!  Em C++, esta pseudo-variável denomina-se this 
(conforme introduzido na Aula 2) 
9 
Construtores em C++ 
!  Implementação do construtor 
•  Opção 1 
!  Diferencia o atributo do parâmetro usando this	
•  Permite nomes mais adequados 
10 
1		Sensor::Sensor(int	numero,	Residencia	*residencia)	{	
2				this->numero	=	numero;	
3				this->residencia	=	residencia;	
4		}	
Construtores em C++ 
!  Implementação do construtor 
•  Opção 2 (recomendada) 
!  Ainda usa os nomes dos atributos como parâmetros 
•  Facilita a leitura para quem usa o construtor 
11 
Sensor::Sensor	(int	numero,	Residencia	*residencia)	:	
		numero	(numero),	residencia	(residencia)	{	
		//	...	
}	
Atributo Parâmetro Atributo Parâmetro 
Construtores em C++ 
!  Chamada do construtor 
!  O que ocorreria neste caso? 
12 
Residencia	*r	=	new	Residencia	();	//	Construtor	sem	parâmetros	
		
Sensor	*s1	=	new	Sensor(1,	r);	//	Construtor	com	parâmetros	
Sensor	*s2	=	new	Sensor(2,	r);	
Residencia	*r;	
		
Sensor	*s1	=	new	Sensor(1,	r);		
Sensor	*s2	=	new	Sensor(2,	r);	
NULL 
!  Representa um ponteiro que aponta para 
nenhum valor 
!  explicado na Aula 2 
13 
	1		#include	<iostream>	
	2		...	
	3			
	4		int	main	(int	argc,	char**	argv)	{	
	5				int	*p;	//	endereço	indefinido	
	6				p	=	NULL;	//	nenhum	valor	
	7			
	8				if	(p	==	NULL)	{	//	é	possível	testar	
	9						...	
10				}	
11		}	
Necessário fazer um 
include para usar o NULL	
 
(Está definido em 
várias bibliotecas) 
Construtores em C++ 
!  Se quisermos criar um Sensor fora de uma 
Residência, podemos indicar um objeto vazio 
usando NULL: 
14 
Sensor	*s1	=	new	Sensor(1,	NULL);		
Sensor	*s2	=	new	Sensor(2,	NULL);	
Construtores em C++ 
!  Se um construtor não for especificado, o C++ 
cria um construtor padrão (sem parâmetros) 
•  Usa-se um construtor padrão quando não houver 
nada a ser feito na criação 
15 
class	Residencia	{	
public:	
		Residencia();	
};	
class	Residencia	{	
};	
Equivalente a 
Observação: se for declarado um construtor sem 
parâmetros, ele precisará ser implementado! 
Construtores 
!  Quais parâmetros o construtor deve ter? 
•  Depende do uso! 
!  Algumas perguntas 
•  Que informações são necessárias para inicializar o objeto? 
•  O valor do atributo depende do objeto ou pode ser padrão? 
•  Exemplo 
!  classe Sensor 
•  Atributos: numero (int) e residencia (Residencia*) 
!  classe Residência 
•  Atributos: l (ListaLigadaSensores) e disparado (bool) 
16 
Agenda 
1.  Construtores 
2.  Destrutores 
3.  Escopo e gerenciamento de memória 
4.  Constantes 
17 
Destrutores 
!  Em certos casos, seria útil também realizar 
certas operações ao término do ciclo de vida de 
um objeto, quando este deve ser destruído 
!  Analogamente ao caso dos construtores, em 
POO existem métodos que são 
automaticamente executados nestes casos 
!  Tais métodos denominam-se destrutores 
18 
Destrutores 
!  Método chamado quando um objeto é destruído 
•  Ele deve liberar os recursos usados 
!  Declaração de um destrutor em C++ 
•  Não tem parâmetros e nem retorno 
•  Nome da classe com ~ 
19 
1		class	Sensor	{	
2		public:	
3				...	
4			
5				Sensor	(int	numero,	Residencia	*residencia);	//	Construtor	
6				~Sensor();	//	Destrutor	
7				...	
8		};	
Destrutor 
Destrutores em C++ 
!  Implementação do destrutor 
!  Quando um objeto é destruído? 
!  Quando um destrutor é executado? 
20 
1		Sensor::~Sensor()	{	
2				cout	<<	"Destruido"	<<	endl;	
3		}	
Agenda 
1.  Construtores 
2.  Destrutores 
3.  Escopo e gerenciamento de memória 
4.  Constantes 
21 
0x000000	
...	
0x000080	
0x000084	
0x000088	
0x00008C	
...	
Ciclo de vida de um objeto 
!  Criação, uso e destruição 
22 
s: Sensor 
Criação 
numero = 3 
residencia = r 
detectarAcao() 
Destruição 
0x000000	
...	
? 0x000080	
? 0x000084	
0x000088	
0x00008C	
...	detectarAcao() 
Memória 
Atribui valor 
Atribui valor 
Executa
 método
 
Execu
ta mét
odo 
0x000000	
...	
3 0x000080	
? 0x000084	
0x000088	
0x00008C	
...	
0x000000	
...	
3 0x000080	
Posição de r 0x000084	
0x000088	
0x00008C	
...	
Escopo 
!  Um bloco define o escopo de uma variável 
•  Bloco: conjunto de comandos entre "{" e "}" 
•  A variável e o objeto existem naquele bloco 
23 
1		if	(i	<	maximo)		
2		{	
3				int	j;	
4				j	=	maximo;	
5		}	
6			
7		if	(j	>	2)		...;	
Erro de compilação. 
A variável “j" não está declarada neste escopo! 
Aqui a variável j é desalocada 
da memória 
Alocação de memória 
!  Problema: alocação de memória 
•  O C++ não sabequantos objetos serão criados antes 
da execução 
•  Mesmo problema com vetores 
24 
1		int	vetor1[50];	
2			
3		int	quantidade;	
4		cin	>>	quantidade;	
5		int	vetor2[quantidade];	
Válido 
Problema: qual o tamanho? 
Alocação de memória 
!  Alocação estática de vetores 
 
25 
int	inteiros	[5];					//	Vetor	para	5	inteiros	
		
Sensor	*sensores	[5];	//	Vetor	para	5	sensores	
sensores 
sensores[0] sensores[1] sensores[2] sensores[3] sensores[4] 
for	(int	i=0;	i<5;	i++)	{	
		inteiros[i]	=	i+1;	
		sensores[i]	=	new	Sensor(i,	NULL);	
}	
Alocação de memória 
!  O C++ permite alocar memória dinamicamente 
•  Usa uma área especial de memória 
!  Chamada heap / free store / memória dinâmica 
!  Programador deve gerenciar a memória 
•  Alocar o elemento → new	
•  Desalocar o elemento → delete	
26 
Alocação de memória 
!  New: alocação no heap 
•  Retorna um identificador para o elemento criado 
•  Chama o construtor 
!  Delete: desalocação do elemento no heap 
•  Chama o destrutor 
27 
int	*p	=	new	int;	
Residencia	*r	=	new	Residencia	();		
Sensor	*s1	=	new	Sensor;								//	Construtor	sem	parâmetros	
Sensor	*s2	=	new	Sensor(5,	r);		//	Construtor	com	parâmetros	
int	*p	=	new	int;	
...	
delete	p;	
Sensor	*s1	=	new	Sensor;	
...	
delete	s1;	
Alocação de memória 
!  Alocação dinâmica de vetores 
 
28 
int	maximo;	
cin	<<	maximo;	
		
int	*inteiros	=	new	int[maximo];										//	Vetor	para	max.	inteiros	
Sensor	**sensores	=	new	Sensor*	[maximo];	//	Vetor	para	max.	sensores	
sensores 
sensores[0] sensores[1] sensores[2] sensores[3] sensores[4] 
for	(int	i=0;	i<maximo;	i++)	{	
		inteiros[i]	=	i+1;	
		sensores[i]	=	new	Sensor(i,	NULL);	
}	
Alocação de memória 
!  Desalocação de vetores 
 
29 
int	*inteiros	=	new	int[10];	
...	
delete[]	inteiros;	
		
Sensor	**sensores	=	new	Sensor*[maximo];	
...	
delete[]	sensores;	
Gerenciamento de memória 
!  Regra geral 
!  Problemas comuns 
•  Objetos criados (new) mas não apagados (delete) 
!  Memory leak 
•  Objeto apagado prematuramente 
!  A área de memória pode ter outro uso! 
•  Objeto apagado mais de uma vez 
!  Não se sabe o que será apagado na segunda vez 
30 
Toda a vez que algo for alocado (new), ele deve ser em 
algum momento desalocado (delete)! 
Gerenciamento de memória 
!  Em algumas linguagens o ambiente gerencia a 
destruição dos objetos 
•  Exemplo: Java, Perl, Python e C# 
•  Vantagem: facilidade 
•  Desvantagens: 
!  O ambiente precisa controlar os objetos: recursos 
!  A destruição é feita quando o ambiente quer 
!  Compromisso entre controle X facilidade 
31 
Agenda 
1.  Construtores 
2.  Destrutores 
3.  Escopo e gerenciamento de memória 
4.  Constantes 
32 
Constantes 
!  É possível definir constantes em C++ 
•  Modificador const	
!  O valor da constante deve ser atribuído na declaração da 
variável 
33 
const	int	x	=	0;																																	//	x	não	pode	
																																																	//	ser	alterado	
const	Sensor	*s	=	new	Sensor(1,	new	Residencia);	//	s	não	pode		
																																																	//	ser	alterado	
x	=	3;	
s->numero	=	4;	
Erro de compilação. 
Inválido alterar uma constante. 
Constantes 
!  Um parâmetro pode ser uma constante 
•  Não pode ser alterado pelo método 
•  Verificação de erros em tempo de compilação 
•  Exemplo 
34 
void	processar(const	Sensor	*s)	{	
		...	
		s->numero	=	4;	
}	
Erro de compilação. 
Objeto não pode ser alterado 
Constantes 
!  O retorno de uma função / método também 
pode ser uma constante 
35 
const	int*	criarVetor()	{	
		return	new	int[3];	
}	
const	int	*vetor	=	criarVetor();	
		
vetor[0]	=	3;	 Erro de compilação. 
Não pode ser alterado 
Compilador obriga que a variável seja um const int * 
Constantes 
!  É possível definir que um método não pode 
alterar o objeto 
36 
class	Sensor	{	
public:	
		int	numero;	
		Residencia	*residencia;	
		
		Sensor(int	numero,	Residencia	*residencia);	
		void	detectarAcao()	const;	
};	
Não pode alterar 
os atributos 
void	Sensor::detectarAcao()	const	{	
		...	
		this->numero	=	0;	
}	
Erro em tempo de 
compilação 
Agenda 
1.  Construtores 
2.  Destrutores 
3.  Escopo e gerenciamento de memória 
4.  Constantes 
 
ADENDO: Entrada de dados pelo teclado em C++ 
37 
Detalhes de C++ 
!  Obter uma string do teclado 
•  Solução: função getline 
!  Uso: getline(cin,	umaString)	
•  Não captura o '\n' 
!  Necessário fazer #include	<string>	
•  ...o texto digitado anteriormente por um cin pode ser 
"capturado" pelo getline... 
!  Necessário ignorar os caracteres digitados anteriormente 
•  Método ignore do cin	
38 
string	texto1,	texto2;	
cin	>>	texto1;	
cin	>>	texto2;	
Não considera texto 
com espaço... 
A próxima palavra digitada 
vai para texto2 
cin.ignore(100,	'\n')	//	ignora	100	caracteres	ou	até	
																						//	encontrar	um	'\n'	
Detalhes de C++ 
!  Exemplo 
39 
	1		#include	<iostream>	
	2		#include	<string>	
	3		using	namespace	std;	
	4			
	5		int	main	(int	argc,	char**	argv)	{	
	6				string	texto1,	texto2;	
	7				cin	>>	texto1;	
	8			
	9				cin.ignore	(100,	'\n');	
10				getline	(cin,	texto2);	
11			
12				cout	<<	texto1	<<	endl;	
13				cout	<<	texto2	<<	endl;	
14				return	0;	
15		}	
Bibliografia 
!  Budd, T. An Introduction to Object-Oriented 
Programming. Addison-Wesley, 3rd ed. 2002. 
Capítulo 5. 
!  Lafore, R. Object-Oriented Programming in C++. 
Sams, 4th ed. 2002. Capítulo 6. 
!  Savitch, W. C++ Absoluto. Pearson, 1st ed. 
2003. Seções 7.1 e 10.3. 
40

Continue navegando