46
Aloca Aloca ç ç ão de Mem ão de Mem ó ó ria ria e uso de ponteiros e uso de ponteiros Prof. Leandro Tonietto Estruturas de Dados em C++ - Unisinos [email protected] http://www.inf.unisinos.br/~ltonietto abr-10

Aloca ção de Mem ória e uso de ponteirosprofessor.unisinos.br/ltonietto/tsi/edc/AlocacaoMemoria_CPP.pdf · Dinâmica significa a área de memória que armazena um valor deve ser

  • 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.

27-abr-10 Leandro Tonietto 46

Referências bibliográficas

DEITEL, Harvey M., DEITEL, Paul J. C++: como programar. 5ed. Pearson Educationdo Brasil Ltda., págs 312—374. 2006.