A apresentação está carregando. Por favor, espere

A apresentação está carregando. Por favor, espere

1 Aula 6 Classes que reservam recursos externos. 2003/2004 Programação Orientada para Objectos 2 PilhaDeInt : interface /** Representa pilhas de int.

Apresentações semelhantes


Apresentação em tema: "1 Aula 6 Classes que reservam recursos externos. 2003/2004 Programação Orientada para Objectos 2 PilhaDeInt : interface /** Representa pilhas de int."— Transcrição da apresentação:

1 1 Aula 6 Classes que reservam recursos externos

2 2003/2004 Programação Orientada para Objectos 2 PilhaDeInt : interface /** Representa pilhas de int. @invariant itens aponta matriz com capacidade_actual itens e capacidade_inicial <= capacidade_actual e 0 <= número_de_itens <= capacidade_actual. */ class PilhaDeInt { public: typedef int Item; /** Constrói pilha vazia. @pre V. @post estáVazia(). */ PilhaDeInt(); /** Destrói a pilha. @pre V. @post recursos externos reservados foram libertados. */ ~PilhaDeInt();

3 2003/2004 Programação Orientada para Objectos 3 PilhaDeInt : interface /** Devolve o item que está no topo da pilha. @pre ¬estáVazia(). @post topo idêntico ao item no topo de *this. */ Item const& topo() const; /** Indica se a pilha está vazia. @pre V. @post estáVazia = *this está vazia. */ bool estáVazia() const; /** Devolve altura da pilha. @pre V. @post altura = altura de *this. */ int altura() const;

4 2003/2004 Programação Orientada para Objectos 4 PilhaDeInt : interface /** Põe um novo item na pilha (no topo). @pre V. @post *this contém um item adicional no topo igual a novo_item. */ void põe(Item const& novo_item); /** Tira o item que está no topo da pilha. @pre ¬ estáVazia(). @post *this contém os itens originais menos o do topo. */ void tiraItem();

5 2003/2004 Programação Orientada para Objectos 5 PilhaDeInt : implementação private: static int const capacidade_inicial = 32; int capacidade_actual; Item* itens; int número_de_itens; bool cumpreInvariante() const; }; inline PilhaDeInt::PilhaDeInt() : capacidade_actual(capacidade_inicial), itens(new Item[capacidade_actual]), número_de_itens(0) { assert(cumpreInvariante()); }

6 2003/2004 Programação Orientada para Objectos 6 PilhaDeInt : implementação inline PilhaDeInt::~PilhaDeInt() { assert(cumpreInvariante()); delete[] itens; } PilhaDeInt::Item const& PilhaDeInt::topo() const { assert(cumpreInvariante()); return itens[número_de_itens - 1]; }

7 2003/2004 Programação Orientada para Objectos 7 PilhaDeInt : implementação bool PilhaDeInt::estáVazia() const { assert(cumpreInvariante()); return altura() == 0; } int PilhaDeInt::altura() const { assert(cumpreInvariante()); return número_de_itens; }

8 2003/2004 Programação Orientada para Objectos 8 PilhaDeInt : implementação void PilhaDeInt::põe(Item const& novo_item) { assert(cumpreInvariante()); if(número_de_itens == capacidade_actual) { Item* novos_itens = new Item[capacidade_actual * 2]; for(int i = 0; i != número_de_itens; ++i) novos_itens[i] = itens[i]; capacidade_actual *= 2; delete[] itens; itens = novos_itens; } itens[número_de_itens] = novo_item; ++número_de_itens; assert(cumpreInvariante()); }

9 2003/2004 Programação Orientada para Objectos 9 PilhaDeInt : implementação void PilhaDeInt::tiraItem() { assert(cumpreInvariante()); assert(not estáVazia()); --número_de_itens; assert(cumpreInvariante()); } bool PilhaDeInt::cumpreInvariante() const { return capacidade_inicial <= capacidade_actual and 0 <= número_de_itens <= capacidade_actual; }

10 2003/2004 Programação Orientada para Objectos 10 Classes que reservam recursos externos Princípios usados: 1. Todas as variáveis dinâmicas construídas devem ser destruídas 2. A entidade encarregue de construir deve tipicamente responsabilizar-se pela destruição: política quem constrói, destrói Recursos externos: memória, ficheiros, …

11 2003/2004 Programação Orientada para Objectos 11 Construtor por cópia O que sucede depois de: PilhaDeInt p1; PilhaDeInt p2 = p1; // Ou PilhaDeInt p2(p1);

12 2003/2004 Programação Orientada para Objectos 12 Construtor por cópia itens[0] : int itens[1] : int itens[2] : int itens[31] : int :int[32] … 0 número_de_itens : int 32 capacidade_actual : int p1: PilhaDeInt itens : int* 0 número_de_itens : int 32 capacidade_actual : int P2: PilhaDeInt itens : int* As duas pilhas partilham orgãos internos.

13 2003/2004 Programação Orientada para Objectos 13 Construtor por cópia O C++ fornece um construtor por cópia implícito que se limita a construir os atributos de instância da classe, copiando-os um a um

14 2003/2004 Programação Orientada para Objectos 14 Valor vs. Referência Semântica de valor: Iguais, mas independentes Semântica de referência: Um novo nome para a mesma coisa (identidade) Igualdade Identidade

15 2003/2004 Programação Orientada para Objectos 15 Construtor por cópia: declaração class PilhaDeInt { public: … /** Constrói pilha igual a original. @pre V. @post *this = original. */ PilhaDeInt(PilhaDeInt const& original); … private: … }; Sempre por referência!

16 2003/2004 Programação Orientada para Objectos 16 Construtor por cópia: definição PilhaDeInt::PilhaDeInt(PilhaDeInt const& original) : capacidade_actual(?), itens(?), número_de_itens(?) { assert(original.cumpreInvariante()); ? assert(cumpreInvariante()); // assert(*this == original) se definirmos o operador ==. }

17 2003/2004 Programação Orientada para Objectos 17 Construtor por cópia: definição PilhaDeInt::PilhaDeInt(PilhaDeInt const& original) : capacidade_actual(?), itens(?), número_de_itens(original.número_de_itens) { assert(original.cumpreInvariante()); ? assert(cumpreInvariante()); // assert(*this == original) se definirmos o operador ==. }

18 2003/2004 Programação Orientada para Objectos 18 Construtor por cópia: definição PilhaDeInt::PilhaDeInt(PilhaDeInt const& original) : capacidade_actual(original.capacidade_actual), itens(new Item[capacidade_actual]), número_de_itens(original.número_de_itens) { assert(original.cumpreInvariante()); ? assert(cumpreInvariante()); // assert(*this == original) se definirmos o operador ==. }

19 2003/2004 Programação Orientada para Objectos 19 Construtor por cópia: definição PilhaDeInt::PilhaDeInt(PilhaDeInt const& original) : capacidade_actual(original.capacidade_actual), itens(new Item[capacidade_actual]), número_de_itens(original.número_de_itens) { assert(original.cumpreInvariante()); for(int i = 0; i != número_de_itens; ++i) itens[i] = original.itens[i]; assert(cumpreInvariante()); // assert(*this == original) se definirmos o operador ==. }

20 2003/2004 Programação Orientada para Objectos 20 Atribuição por cópia O que acontece depois de: PilhaDeInt p1; for(int i = 0; i != 3; ++i) p1.põe(i); PilhaDeInt p2; p2 = p1;

21 2003/2004 Programação Orientada para Objectos 21 3 número_de_itens : int 32 capacidade_actual : int p2 PilhaDeInt itens : int* Atribuição por cópia 0 itens[0] : int 1 itens[1] : int 2 itens[2] : int itens[31] : int :int[32] … 3 número_de_itens : int 32 capacidade_actual : int p1: PilhaDeInt itens : int* 0 número_de_itens : int 32 capacidade_actual : int p2 PilhaDeInt itens : int* itens[0] : int itens[1] : int itens[2] : int itens[31] : int :int[32] … As duas pilhas partilham orgãos internos. Fuga de memória.

22 2003/2004 Programação Orientada para Objectos 22 Atribuição por cópia Inicialização Atribuição Já existe um objecto, que tem de mudar de valor O C++ fornece implicitamente às classes um operador de atribuição por cópia que atribui cada uma das variáveis membro de instância se existirem constantes ou referências de instância este operador não é fornecido

23 2003/2004 Programação Orientada para Objectos 23 Atribuição por cópia: declaração class PilhaDeInt { public: … /** Torna *this igual a modelo. @pre V. @post *this = modelo. */ PilhaDeInt& operator = (PilhaDeInt const& modelo); … private: … };

24 2003/2004 Programação Orientada para Objectos 24 Atribuição por cópia: definição PilhaDeInt& PilhaDeInt::operator = (PilhaDeInt const& modelo) { assert(cumpreInvariante() and modelo.cumpreInvariante()); ? assert(cumpreInvariante()); // assert(*this == original) se definirmos o operador ==. }

25 2003/2004 Programação Orientada para Objectos 25 Atribuição por cópia: definição PilhaDeInt& PilhaDeInt::operator = (PilhaDeInt const& modelo) { assert(cumpreInvariante() and modelo.cumpreInvariante()); ? capacidade_actual = modelo.capacidade_actual; número_de_itens = modelo.número_de_itens; assert(cumpreInvariante()); // assert(*this == original) se definirmos o operador ==. }

26 2003/2004 Programação Orientada para Objectos 26 Atribuição por cópia: definição PilhaDeInt& PilhaDeInt::operator = (PilhaDeInt const& modelo) { assert(cumpreInvariante() and modelo.cumpreInvariante()); delete[] itens; itens = new Item[modelo.capacidade_actual]; ? capacidade_actual = modelo.capacidade_actual; número_de_itens = modelo.número_de_itens; assert(cumpreInvariante()); // assert(*this == original) se definirmos o operador ==. }

27 2003/2004 Programação Orientada para Objectos 27 Atribuição por cópia: definição PilhaDeInt& PilhaDeInt::operator = (PilhaDeInt const& modelo) { assert(cumpreInvariante() and modelo.cumpreInvariante()); delete[] itens; itens = new Item[modelo.capacidade_actual]; for(int i = 0; i != modelo.número_de_itens; ++i) itens[i] = modelo.itens[i]; capacidade_actual = modelo.capacidade_actual; número_de_itens = modelo.número_de_itens; assert(cumpreInvariante()); // assert(*this == original) se definirmos o operador ==. }

28 2003/2004 Programação Orientada para Objectos 28 Atribuição por cópia O que deveria acontecer depois de: PilhaDeInt p; p.põe(1); p.põe(2); p = p; Nada!

29 2003/2004 Programação Orientada para Objectos 29 Mas o que acontece é… 1 itens[0] : int 2 itens[1] : int itens[31] : int :int[32] … 2 número_de_itens : int 32 capacidade_actual : int p1: PilhaDeInt itens : int* ? itens[0] : int ? itens[1] : int itens[31] : int :int[32] … Lixo!

30 2003/2004 Programação Orientada para Objectos 30 Atribuição por cópia: definição PilhaDeInt& PilhaDeInt::operator = (PilhaDeInt const& modelo) { assert(cumpreInvariante() and modelo.cumpreInvariante()); if(*this != modelo) { delete[] itens; itens = new Item[modelo.capacidade_actual]; for(int i = 0; i != modelo.número_de_itens; ++i) itens[i] = modelo.itens[i]; capacidade_actual = modelo.capacidade_actual; número_de_itens = modelo.número_de_itens; } assert(cumpreInvariante()); // assert(*this == modelo) se definirmos o operador ==. } Não está definido! Mas, como comparar pilhas?

31 2003/2004 Programação Orientada para Objectos 31 Igualdade vs. Identidade Identidade - Alteridade Se duas coisas são a mesma, então são iguais Igualdade - Desigualdade Se duas coisas são diferentes, então são outras Se duas coisas são iguais podem ou não ser a mesma O endereço é que marca a identidade das instâncias

32 2003/2004 Programação Orientada para Objectos 32 Igualdade vs. Identidade Sejam i e j dois nomes de int int i = 0; int& j = i; ou int i = 0; int j = i; Como saber se i e j são a mesma variável?

33 2003/2004 Programação Orientada para Objectos 33 Igualdade vs. Identidade Duas instâncias são a mesma se e só se tiverem o mesmo endereço! &i == &j é o mesmo que dizer que i e j são o mesmo indivíduo ou instância i == j não implica &i == &j &i == &j implica i == j

34 2003/2004 Programação Orientada para Objectos 34 Atribuição por cópia: definição PilhaDeInt& PilhaDeInt::operator = (PilhaDeInt const& modelo) { assert(cumpreInvariante() and modelo.cumpreInvariante()); if(&*this != &modelo) { delete[] itens; itens = new Item[modelo.capacidade_actual]; for(int i = 0; i != modelo.número_de_itens; ++i) itens[i] = modelo.itens[i]; capacidade_actual = modelo.capacidade_actual; número_de_itens = modelo.número_de_itens; } assert(cumpreInvariante()); // assert(*this == modelo) se definirmos o operador ==. } & e * são o inverso um do outro.

35 2003/2004 Programação Orientada para Objectos 35 Atribuição por cópia: definição PilhaDeInt& PilhaDeInt::operator = (PilhaDeInt const& modelo) { assert(cumpreInvariante() and modelo.cumpreInvariante()); if(this != &modelo) { delete[] itens; itens = new Item[modelo.capacidade_actual]; for(int i = 0; i != modelo.número_de_itens; ++i) itens[i] = modelo.itens[i]; capacidade_actual = modelo.capacidade_actual; número_de_itens = modelo.número_de_itens; } assert(cumpreInvariante()); // assert(*this == modelo) se definirmos o operador ==. }

36 2003/2004 Programação Orientada para Objectos 36 Atribuição por cópia: definição PilhaDeInt& PilhaDeInt::operator = (PilhaDeInt const& modelo) { assert(cumpreInvariante() and modelo.cumpreInvariante()); if(this != &modelo) { if(capacidade_actual != modelo.capacidade_actual) { delete[] itens; itens = new Item[modelo.capacidade_actual]; } for(int i = 0; i != modelo.número_de_itens; ++i) itens[i] = modelo.itens[i]; capacidade_actual = modelo.capacidade_actual; número_de_itens = modelo.número_de_itens; } assert(cumpreInvariante()); // assert(*this == modelo) se definirmos o operador ==. } Reciclagem da matriz.

37 2003/2004 Programação Orientada para Objectos 37 Classes que reservam recursos externos Construção (Construtor por cópia) Destruição (Destrutor) Cópia (Operador de atribuição por cópia) Igualdade Identidade Semântica de valor vs. semântica de referência

38 2003/2004 Programação Orientada para Objectos 38 Aula 6: Sumário Classes que reservam recursos externos Problemas comuns Construtores e destrutores Construção por cópia Semântica de valor vs. semântica de referência Atribuição por cópia O exemplo das pilhas


Carregar ppt "1 Aula 6 Classes que reservam recursos externos. 2003/2004 Programação Orientada para Objectos 2 PilhaDeInt : interface /** Representa pilhas de int."

Apresentações semelhantes


Anúncios Google