Upload
lediep
View
213
Download
0
Embed Size (px)
Citation preview
AlocaAlocaçção de Memão de Memóória ria
e uso de ponteirose uso de ponteiros
Prof. Leandro ToniettoEstruturas de Dados em C++ - Unisinos
[email protected]://www.inf.unisinos.br/~ltonietto
abr-10
27-abr-10 Leandro Tonietto 2
Sumário
IntroduçãoAlocação de variáveis: tipos primitivosAlocação de ponteiros: tipos primitivosManipulação de strings como array de caracteres Ponteiros e instanciação de objetos com new
Alocação dinâmica de vetores
27-abr-10 Leandro Tonietto 3
Introdução
Qualquer dado para ser processado deve estar na memóriaComo memória podemos entender como slots de bytes para armazenamento temporário.Todas as variáveis são posições de memóriaVariáveis na memória possuem: nome, tipo, tamanho e valor que armazenam.
4
5
n
...
3
2
1
0
Memória
27-abr-10 Leandro Tonietto 4
Alocação de variáveis: tipos primitivos
A alocação de variáveis de tipos de dados primitivos (int, double, float, char, boole etc) é estática, com acesso direto a valores e é trivial. � Estática significa que alocada no momento de entrada do seu escopo e será descarregada no final do escopo, tudo de forma “automática” feita pelo compilador.
� Chamamos de alocação implícita. Portanto, a simples declaração de uma variável implica em alocação de memória.
Exemplo: int v1;
27-abr-10 Leandro Tonietto 5
Alocação de variáveis: tipos primitivos
?4
?5
n
...
3
2
1
0
?
?
?
?
?
?
Memóriaint v1;
Código-fonte:
v1
v1 está associado com a posição 0 (zero), que é a próxima livre.
v1 está associado com a posição 0 (zero), que é a próxima livre.
27-abr-10 Leandro Tonietto 6
Alocação de variáveis: tipos primitivos
?4
?5
n
...
3
2
1
0
?
?
?
?
?
?
Memóriaint v1;
int v2;
Código-fonte:
v1
v2 está associado com a posição 1, que é a próxima
livre.
v2 está associado com a posição 1, que é a próxima
livre.
v2
27-abr-10 Leandro Tonietto 7
Alocação de variáveis: tipos primitivos
?4
?5
n
...
3
2
1
0
?
?
?
?
3
5
Memóriaint v1;
int v2;
v1 = 5;
v2 = 3;
Código-fonte:
v1
Quando atribuímos um valor para uma variável, estamos fazendo com a
posição de memória da variável tenha este valor. Ex.: v1=5, significa posição
zero recebe valor 5
Quando atribuímos um valor para uma variável, estamos fazendo com a
posição de memória da variável tenha este valor. Ex.: v1=5, significa posição
zero recebe valor 5
v2
27-abr-10 Leandro Tonietto 8
Alocação de variáveis primitivos
?4
?5
n
...
3
2
1
0
?
?
?
8
3
5
Memóriaint v1;
int v2;
v1 = 5;
v2 = 3;
int r = v1+v2;
Código-fonte:
v1
Da mesma forma, a variável r foi alocada na próxima posição livre para int e recebeu um valor, no caso a soma dos valores armazenados nas posições 0 e 1;
também podemos dizer que é a soma das variáveis v1 e v2, porque v1 e v2 são como “apelidos” para as
posições 0 e 1 da memória.
Da mesma forma, a variável r foi alocada na próxima posição livre para int e recebeu um valor, no caso a soma dos valores armazenados nas posições 0 e 1;
também podemos dizer que é a soma das variáveis v1 e v2, porque v1 e v2 são como “apelidos” para as
posições 0 e 1 da memória.
v2
r
27-abr-10 Leandro Tonietto 9
Alocação de ponteiros: tipos primitivos
A alocação de ponteiros para variáveis de tipos primitivos implica alocação dinâmica, com manipulação indireta a valores e não é trivial.� Dinâmica significa a área de memória que armazena um valor deve ser alocada explicitamente no momento da sua utilização. Portanto, sem alocação previa.
� Chamamos de alocação explícita. Portanto, a simples declaração de uma variável NÃO implica em alocação de memória, deve-se alocar memória primeiro para depois utilizá-la.
Exemplo: int *p1;
p1 = new int;
27-abr-10 Leandro Tonietto 10
Alocação de ponteiros: tipos primitivos
?4
?5
n
...
3
2
1
0
?
?
?
?
?
5
Memóriaint v1;
v1 = 5;
Código-fonte:
v1
v1 está associado com a posição 0 (zero) e recebe o
valor 5.
v1 está associado com a posição 0 (zero) e recebe o
valor 5.
27-abr-10 Leandro Tonietto 11
Alocação de ponteiros: tipos primitivos
?4
?5
n
...
3
2
1
0
?
?
?
?
?
5
Memóriaint v1;
v1 = 5;
int *p1;
Código-fonte:
v1
Criado um ponteiro (p1) para int (int *). O
ponteiro, assim como a variável não tem valor
inicial.
Criado um ponteiro (p1) para int (int *). O
ponteiro, assim como a variável não tem valor
inicial.
p1
27-abr-10 Leandro Tonietto 12
Alocação de ponteiros: tipos primitivos
?4
?5
n
...
3
2
1
0
?
?
?
?
&5
5
Memóriaint v1;
v1 = 5;
int *p1;
p1 = v1; //?
Código-fonte:
v1
Quando atribuímos um valor para um ponteiro, estamos atribuindo um endereço de memória e não exatamente
um valor (dado).
Quando atribuímos um valor para um ponteiro, estamos atribuindo um endereço de memória e não exatamente
um valor (dado).
p1
ERRO DE LÓGICA NO PROGRAMA:p1 = v1 é a mesma coisa que p1=5, que significa que p1 apontará para o endereço 5 da memória.
ERRO DE LÓGICA NO PROGRAMA:p1 = v1 é a mesma coisa que p1=5, que significa que p1 apontará para o endereço 5 da memória.
27-abr-10 Leandro Tonietto 13
Alocação de ponteiros: tipos primitivos
?4
?5
n
...
3
2
1
0
?
?
?
?
&0
5
Memóriaint v1;
v1 = 5;
int *p1;
p1 = &v1; //?
Código-fonte:
v1
Para utilizarmos com eficiência ponteiros, devemos atribuir para eles endereços de variáveis ou de memória previamente alocados. Para informar obter o endereço de memória de uma variável deve-se utilizar o operador “&”
Para utilizarmos com eficiência ponteiros, devemos atribuir para eles endereços de variáveis ou de memória previamente alocados. Para informar obter o endereço de memória de uma variável deve-se utilizar o operador “&”
p1
Agora está correto, pois p1 recebe o endereço de v1. Se diz, então, que p1 aponta para v1, logo p1 aponta para o endereço 0 (zero) da memória. A instrução p1=&v1 é igual a p1=0
Agora está correto, pois p1 recebe o endereço de v1. Se diz, então, que p1 aponta para v1, logo p1 aponta para o endereço 0 (zero) da memória. A instrução p1=&v1 é igual a p1=0
27-abr-10 Leandro Tonietto 14
Resumo alocação de ponteiros
Para criar ponteiros� Uso do asterisco antes do nome da variável
• int *ptr;
Para atribuir um endereço de uma variável para um ponteiro� Uso do “e” comercial antes da variável
• ptr = &v1;
Usando o valor de uma variável apontada por um ponteiro� Uso do asterisco antes da variável de ponteiro
• *ptr
27-abr-10 Leandro Tonietto 15
Resumo alocação de ponteiros
Exemplo de código:
#include <iostream>
int main(){
int v1;
v1 = 0;
int *p1 = &v1;
cout << “v1 está na posição ” << &v1 <<
“ e tem o valor ” << v1 << endl;
cout << “p1 está na posição ” << &p1 <<
“ e tem o valor ” << p1 <<
“. Valor da posição de mem. Apontada por p1” <<
*p1 << endl;
return 0;
}
27-abr-10 Leandro Tonietto 16
Alocação de ponteiros: dicas de sobrevivência!!
Inicializando ponteiros� Uso de NULL ou 0 (são equivalentes)� ptr = NULL; // ou ptr = 0;
Podem ser criados ponteiros para qualquer tipo de dados, inclusive tipos criados pelo usuário� Dica! Use o sufixo ptr nas variáveis de ponteiro
Importante: Sempre inicialize os ponteiros para preservar sua sanidade :-)� Um ponteiro não inicializado aponta para uma área qualquer de memória, provavelmente, uma área inválida de memória. Erro: access violation.
27-abr-10 Leandro Tonietto 17
Strings como array de char
Uma texto é formado várias letras, assim como uma string (cadeia de caracteres) é formada por vários dados do tipo char.Exemplo:� char c; // declaramos uma letra;
� char t[10]; //declaramos um texto com 10 letras.
Problema: quando é necessário representar um texto com tamanho desconhecido, o que podemos fazer?
27-abr-10 Leandro Tonietto 18
Strings como array de char
A solução é utilizar um ponteiro para char.� Exemplo:
char *t; // alocamos um ponteiro para char
A questão agora é: � Todo ponteiro aponta para um endereço de memória, então a string deve estar na memória para ser “apontada”.
� A string é um array de caracteres, contudo ponteiros também são utilizados para manipulação de arrays(aliás, lógica de ponteiros e de arrays estão intimamente relacionadas).
O acesso a caracteres individuais feito como no uso de arrays, pelo caracteres “[” e “]”. Exemplo: t[0].
27-abr-10 Leandro Tonietto 19
Strings como array de char
Exemplo:#include <iostream>
int main(){
char *t = new char[10];
for(int i=0; i<10; i++){
t[i] = 65 + i; // 65=A, 66=B, 67=C, ...
}
char *t2 = t; // o que fizemos aqui?
t2[0] = ‘Z’;
cout << “t =” << t << endl;
cout << “t2=” << t2 << endl;
// o que será impresso na tela?
return 0;
}
27-abr-10 Leandro Tonietto 20
Strings como array de char
Exemplo:
#include <iostream>
int main(){
char *t = new char[8];
for(int i=0; i<8; i++){
t[i] = 65 + i; // 65=A, 66=B, 67=C, ...
}
char *t2 = t; // o que fizemos aqui? ERRO
t2[0] = ‘z’;
cout << “t=” << t < endl;
cout << “t2=” << t2 << endl;
// o que será impresso na tela?
return 0;
}
Atribuímos o mesmo endereço de memória de t para t2. Quando alteramos um impacta no outro. É um erro comum com ponteiros. Solução: criar nova área de memória e copiar os bytes.
Atribuímos o mesmo endereço de memória de t para t2. Quando alteramos um impacta no outro. É um erro comum com ponteiros. Solução: criar nova área de memória e copiar os bytes.
27-abr-10 Leandro Tonietto 21
Strings como array de char
Exemplo:#include <iostream>
int main(){
char *t = new char[8];
for(int i=0; i<8; i++){
t[i] = 65 + i; // 65=A, 66=B, 67=C, ...
}
char *t2 = new char[8];
for(int i=0; i<8; i++){
t2[i] = t[i];
}
t2[0] = ‘z’;
cout << “t=” << t < endl;
cout << “t2=” << t2 << endl;
return 0;
}
Atribuímos o mesmo endereço de memória de t para t2. Quando alteramos um impacta no outro. É um erro comum com ponteiros. Solução: criar nova área de memória e copiar os bytes.
Atribuímos o mesmo endereço de memória de t para t2. Quando alteramos um impacta no outro. É um erro comum com ponteiros. Solução: criar nova área de memória e copiar os bytes.
27-abr-10 Leandro Tonietto 22
Strings como array de char
?4
?5
n
...
3
2
1
0
?
?
?
&1
ZBCDEFGH
&1 t
t2
Memória: ERRO � t2 = t
?4
?5
n
...
3
2
1
0
?
?
ZBCDEFGH
&3
ABCDEFGH
&1 t
t2
Memória: SOLUÇÃO � t2 = new char[8]
27-abr-10 Leandro Tonietto 23
Tarefas
Utilizar lógica de ponteiros para resolver o problema abaixo:� Criar uma classe Pessoa com os atributos nome e endereco do tipo
array de char; e com o atributo inteiro idade.� Criar um main para instanciar 3 pessoas. Solicitar que o usuário
digite os dados de 3 pessoas diferentes e atribuir estes dados para os objetos de pessoa instanciados anteriormente. Quando copiar dados do tipo char *, cuidar para não apontar para a mesma área de memória.
� No main, quando utilize sempre a mesma variável temporária para leitura das strings. Por exemplo: char buffer[80];
� Dicas: • o comando strlen(buffer) retorna o número de caracteres de uma string
• O comando para leitura de strings de maneira mais fácil é: cin.getline(buffer, 80);
27-abr-10 Leandro Tonietto 24
Strings como array de char
Quando fizemos a cópia de strings em classes ocorre o mesmo problema do exemplo (t2=t), então temos que utilizar a mesma solução: criar uma nova área de memória, fazer o atributo ponteiro apontar para ela e copiar as informações individualmente. Exemplo:// no main:
char buffer[80];
cin.getline(buffer,80);
Pessoa p;
p.setNome(buffer);
// na classe Pessoa (.cpp):
void Pessoa::setNome(char *n){
int length = strlen(n);
nome = new char[length+1];
for(int i=0; i<length; i++){
nome[i] = n[i];
}
nome[length] = ‘\0’;
}
ImportanteImportante: em strings : em strings charchar ** o fim o fim
da string deve ser sinalizado com o da string deve ser sinalizado com o caractere caractere terminadorterminador de string: de string: ‘‘\\00’’
27-abr-10 Leandro Tonietto 25
Funções para usar com char *
Nas bibliotecas padrões de C++ podemos fazer uso de diversas funções utilitárias para manipulação de strings do tipo char *.Biblioteca string.h:� #include <string.h>
Funções: strcat, strcpy, strtok, strlen, strcmp e etc.
27-abr-10 Leandro Tonietto 26
Funções para usar com char *
strcat:� Concatena duas strings:
char *c = new char[3];
strcpy(c, "blá");
strcat(c, "blá123"); // ficará “bláblá123”
strcpy:� Copia conteúdo de um string para outra:
char *c = new char[strlen(n)];
strcpy(c, n);// é a mesma coisa que:
void Pessoa::setNome(char *n){
int length = strlen(n);
nome = new char[length+1];
for(int i=0; i<length; i++){
nome[i] = n[i];
}
nome[length] = ‘\0’;
}
27-abr-10 Leandro Tonietto 27
Funções para usar com char *
strtok:� Separa uma string em várias strings, separadas por algum delimitador.
Exemplo:char c[] = "fulano;23;2550.0";
char s[] = ";";
char *t = strtok(c, s); // recebe o primeiro token “fulano”
strlen:� Retorna o tamanho de uma string. Na realidade a quantidade de caracteres
até encontrar o terminador ‘\0’. Exemplo:int length = strlen(nome);
strcmp:� Compara duas strings caractere-a-caractere e retorna:
• 0 (zero) se são iguais • 1 se a primeira é maior que a segunda• -1 se a segunda é maior que a primeiraif(strcmp(s1, s2) == 0)
return s1;
27-abr-10 Leandro Tonietto 28
Funções para usar com char *
Exercícios para praticar strings (desafio 2, entregar no GA):� Crie um programa que leia duas palavras, se forem iguais, escreva:
“palavras são iguais”. Caso a primeira palavra seja maior alfabeticamente, crie uma nova string com a mensagem: “<palavra1> é maior que <palavra2>”. Onde <palavra1> éprimeira palavra digitada e <palavra2> é a segunda.
� Crie um programa que leia uma data fornecida pelo usuário. Considere que o usuário digitará uma string no formato “dd/MM/yyyy”. Imprima os campos da data separadamente. Exemplo: • dia <dd> de <MM> de <yyyy>.
• Onde: <dd>, <mm> e <yyyy> são os valores digitados pelo usuário na string “dd/MM/yyyy”.
� Crie uma calculadora de linha de comando. O usuário digita uma expressão no formato: <operando1> <operador> <operando2> (exemplo: 5 + 6). O programa interpretar a expressão, extraindo os números, realizando a operação desejada e imprimindo o resultado.
27-abr-10 Leandro Tonietto 29
Alocação de variáveis: tipos estruturados
Assim como acontece na alocação de variáveis de tipos primitivos, a alocação de variáveis de tipos estruturados (objetos de classes) é trivial e feita de forma automática e estática:� Estática significa que alocada no momento de entrada do seu escopo e será descarregada no final do escopo, tudo de forma “automática” feita pelo compilador.
� Chamamos de alocação implícita. Portanto, a simples declaração de uma variável implica em alocação de memória.
Exemplo: Pessoa p;
27-abr-10 Leandro Tonietto 30
Alocação de variáveis: tipos estruturados
?12
?13
N
...
11
10
9
0..8
?
?
?
?
?
nome=<?>
endereco=<?>
idade=<?>
Memória
p Pessoa p;
Quando a variável p é declarada ela éautomaticamente alocada na memória do
programação. Então p já tem um endereço de memória e sua área de memória recebe os seus atributos. Repare que os atributos não possuem valores válidos, sendo eles ponteiros ou não.
Quando a variável p é declarada ela éautomaticamente alocada na memória do
programação. Então p já tem um endereço de memória e sua área de memória recebe os seus atributos. Repare que os atributos não possuem valores válidos, sendo eles ponteiros ou não.
27-abr-10 Leandro Tonietto 31
Alocação de variáveis: tipos estruturados
‘i’15
aux[3]=‘s’12
‘L’13
16
14
11
10
9
0..8
‘s’
‘u’
aux[2]=‘i’
aux[1]=‘u’
aux[0]=‘L’
nome=&13
endereco=<?>
idade=<?>
Memória
pPessoa p;
char aux[4];
cin.getline(aux,4);
// aux = “Luis”
p.setNome(aux);
aux
void Pessoa::setNome(char *n){
nome = new char[strlen(n)];
strcpy(nome, n);
}
27-abr-10 Leandro Tonietto 32
Alocação de variáveis: tipos estruturados
Perguntas:� Neste momento, após a linha do setNome(aux), o que aconteceria tentássemos executar imediatamente após a linha: cout << p.getEndereco() ? Justifique?
� Como ficaria o código e o desenho da memória para a atribuição de um endereço para o objeto p?
27-abr-10 Leandro Tonietto 33
Alocação de ponteiros: tipos estruturados
A alocação de ponteiros para objetos de tipos estruturados (classes) implica alocação dinâmica, com manipulação indireta a valores e não é trivial.� Dinâmica significa a área de memória que armazena um valor
deve ser alocada explicitamente no momento da sua utilização. Portanto, sem alocação previa.
� Chamamos de alocação explícita. Portanto, a simples declaração de uma variável NÃO implica em alocação de memória, deve-se alocar memória primeiro para depois utilizá-la (new).
Exemplo: Pessoa *p;
p = new Pessoa();
27-abr-10 Leandro Tonietto 34
Alocação de variáveis: tipos estruturados
&10
?12
?13
N
...
11
10
1..9
?
?
?
?
nome=<?>
endereco=<?>
idade=<?>
Memória
p Pessoa *p;
p = new Pessoa();
Quando a variável p é declarada ela é alocada na memória como um ponteiro, ou seja, ela
não possui um objeto, mas sim um apontamento apenas. Neste caso, deve-se alocar memória explicitamente para que o ponteiro aponte para uma área de memória
válida (operador new). Repare que os atributos ainda não foram alocados.
Quando a variável p é declarada ela é alocada na memória como um ponteiro, ou seja, ela
não possui um objeto, mas sim um apontamento apenas. Neste caso, deve-se alocar memória explicitamente para que o ponteiro aponte para uma área de memória
válida (operador new). Repare que os atributos ainda não foram alocados.
27-abr-10 Leandro Tonietto 35
Alocação de variáveis: tipos estruturados
‘i’16
‘u’15
&10
aux[2]=‘i’12
aux[3]=‘s’13
17
14
11
10
1..9
‘s’
‘L’
aux[1]=‘u’
aux[0]=‘L’
nome=&14
endereco=<?>
idade=<?>
Memória
p
Pessoa *p;
p = new Pessoa();
char aux[80];
cin.getline(aux);
p->setNome(aux);
A alocação dos atributos do objeto apontado pelo ponteiro segue as mesmas regras. Eles devem ser alocados e atribuídos ou copiados para os atributos do objeto. Há uma diferença significativa no uso de ponteiros, ao invés do ponto (.) para acessar os membros do objeto,
agora deve-se utilizar a “->”.
A alocação dos atributos do objeto apontado pelo ponteiro segue as mesmas regras. Eles devem ser alocados e atribuídos ou copiados para os atributos do objeto. Há uma diferença significativa no uso de ponteiros, ao invés do ponto (.) para acessar os membros do objeto,
agora deve-se utilizar a “->”.
aux
27-abr-10 Leandro Tonietto 36
Alocação de variáveis: tipos estruturados
&118
‘i’16
‘u’15
&10
aux[2]=‘i’12
aux[3]=‘s’13
17
14
11
10
1..9
‘s’
‘L’
aux[1]=‘u’
aux[0]=‘L’
nome=&14
endereco=<?>
idade=<?>
Memória
p
Pessoa *p;
p = new Pessoa();
char aux[80];
cin.getline(aux);
p->setNome(aux);
Pessoa *p2;
p2 = p;
aux
p2
27-abr-10 Leandro Tonietto 37
Resumo sobre ponteiros para objetos
Para criar ponteiros� Uso do asterisco antes do nome da variável
• Aluno *ptr;
Para atribuir um endereço de um objeto para um ponteiro� Uso do “e” comercial antes da variável
• Aluno v1;
• ptr = &v1;
Para acessar o conteúdo (objeto) apontado por um ponteiro� Uso do asterisco antes da variável de ponteiro
• *ptr
• (*ptr).setNome(aux); ou ptr->setNome(aux);
27-abr-10 Leandro Tonietto 38
Ponteiros e arrays
Arrays e ponteiros estão intimamente relacionados.Podem ser acessados com a mesma lógica.Um ponteiro pode apontar tanto para um 1 elemento quanto para um array de elementos de um determinado tipo. Não importa o tipo de dados. Sendo assim:int b[3];
int *bPtr;
bPtr = b; // repare que não se usa o &
// outra forma de fazer a mesma coisa
bPtr = &b[0]; // é exatamente a mesma coisa!!
// é possível acessar elementos do array assim:
cout << bPtr[2];
bPtr += 2;
cout << *bPtr; // também imprime terceiro elemento
27-abr-10 Leandro Tonietto 39
Ponteiros e arrays
?4
?5
n
...
3
2
1
0
?
?
&0
b[2]=4
b[1]=1
b[0]=2
Memóriaint b[]={2,1,4};
int *p = b;
cout << p; //imp. 0
cout << *p; // imp. 2
cout << p[2]; // imp. 4
p += 2; // p = 0 + 2 = 2
cout << *p; // imp. 4
Código-fonte:
b
p
Quando se atribui um array para um ponteiro, na verdade está se atribuindo o endereço do primeiro elemento. Os demais podem ser acessados pela mesma lógica de array, usando os caracteres ‘[’ e ‘]’ ou deslocando o ponteiro, com operadores +=, ++, -- e -=.
Quando se atribui um array para um ponteiro, na verdade está se atribuindo o endereço do primeiro elemento. Os demais podem ser acessados pela mesma lógica de array, usando os caracteres ‘[’ e ‘]’ ou deslocando o ponteiro, com operadores +=, ++, -- e -=.
27-abr-10 Leandro Tonietto 40
Resumo: Ponteiros e arrays
Ponteiros podem apontar para arrays; neste caso, deve-se passar o endereço do primeiro elemento: � ptr = b; ou ptr=&b[0]
Acesso aos elementos do array é feito através da lógica de arrays, usando colchetes. Exemplo, para acessar o n-ésimo elemento do array:� ptr[n];
Para arrays de objeto funciona da mesma maneira:� Mensagem *mensagens = new Mensagem[5]; // array
� mensagens[2].setTexto(buffer);
27-abr-10 Leandro Tonietto 41
Ponteiros para ponteiros
Muitas vezes precisamos criar arrays de ponteiros para representar uma coleção de objetos que são de subclasses diferentes, mas de uma mesmasuperclasse. Por exemplo� Criar um array de Pessoas, sendo que é possível instanciar cada registro como
Aluno ou Professor.� Criar um array de objetos da classe abstrata de Processo, sendo que é possível
instanciar como ProcessoCalculo, ou ProcessoLeitura ou outro subtipo qualquer.Exemplo de declaração de array de ponteiros:// cria um array de 100 ponteiros para objetos da classe Pessoa
Pessoa *pessoas[100];
// normalmente, deve-se manter também um contador de tamanho
// lógico do array
int ultimo=0;
// para cada elemento do array a ser utilizado no programa,
// devemos instanciar um objeto
pessoas[ultimo++] = new Professor();
27-abr-10 Leandro Tonietto 42
Ponteiros para ponteiros
Quanto temos arrays de ponteiros ou, simplesmente, precisamos alterar um ponteiro criado num objeto em outro objeto, precisamos passar referências como “ponteiro para ponteiro”.Por exemplo, continuando o exemplo anterior de pessoas:class Impressao {
// para fins de exemplificação não foi criado cpp
void imprimir(Pessoa **p, int ult){
for(int i=0; i<ult; i++){
cout << p[i]->getNome() << endl;
}
}
}
Ainda, podemos aumentar (ou modificar) o array original:class AlgumaOutraClasse {
// para fins de exemplificação não foi criado cpp
void adicionaProfessorFulano(Pessoa **p, int *ult){
p[*ult] = new Professor();
p[*ult]->setNome(“Fulano”);
((Professor*)p[*ult])->setEspecialidade(“Estrutura de Dados”);
(*ult)++;
}
}
**p – é um ponteiro para ponteiro, portanto, podemos receber nesta variável um array de ponteiros
*ult – é um ponteiro para o último elemento lógico do array
27-abr-10 Leandro Tonietto 43
Próximos passos
ExercíciosContinuar apresentação sobre programação OO, com herança, uso de ponteiros para relacionamento classe-base e classe-derivada e polimorfismo.Passagem de parâmetros para funções.
27-abr-10 Leandro Tonietto 44
Exercício
Cria a classe Mensagem que representa uma mensagem de e-mail. Classe deve conter os atributos: remetente, destinatário, assunto e corpo da mensagem. Crie também os métodos necessários para acesso aos atributos. Entretanto, para os atributos remetente e destinatário, deve-se colocar uma validação, ou seja, só serão aceitos endereços de e-mail que:� Contenham mais do 6 caracteres.� Que possuam o caractere ‘@’� Que possuam algum domínio válido “.com”, “.net” ou “.org”Fazer um arquivo main que crie um ponteiro para um objeto mensagem. Alocar memória dinamicamente para o objeto e fazer a leitura dos campos solicitados. Depois imprimir os dados da mensagem na tela.Modifique o código do método setDestinatario(char *d) para receber mais de um destinatário numa string separada por “;” ou “,” e quebrar num array de vários destinatários (utilize a função strtok). Por exemplo: o usuário digita “[email protected];[email protected]” e o método setDestinatario() quebra em duas strings “[email protected]” e “[email protected]”.
27-abr-10 Leandro Tonietto 45
Tarefas
Faça a lista de exercícios que está no site da disciplina.Alguns exercícios vão além do que foi visto atéo momento, tente fazê-los mesmo assim. Para tanto, seria interessante a leitura do capítulo 8 – “Ponteiros e strings baseadas em ponteiros”do livro “C++: como programar”, a partir da pág. 312. Especialmente o as seções que falam sobre “sizeof”, “const” e passagem de parâmetros para funções.� Se não conseguir este livro, você pode qualquer outro que fale nestes assuntos.