38
1 Aula 6 Classes que reservam recursos externos

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

Embed Size (px)

Citation preview

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

1

Aula 6

Classes que reservam recursos externos

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

2003/2004 Programação Orientada para

Objectos2

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();

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

2003/2004 Programação Orientada para

Objectos3

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;

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

2003/2004 Programação Orientada para

Objectos4

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();

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

2003/2004 Programação Orientada para

Objectos5

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());}

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

2003/2004 Programação Orientada para

Objectos6

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];}

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

2003/2004 Programação Orientada para

Objectos7

PilhaDeInt: implementação

bool PilhaDeInt::estáVazia() const{    assert(cumpreInvariante());

    return altura() == 0;}

int PilhaDeInt::altura() const{    assert(cumpreInvariante());

   return número_de_itens;}

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

2003/2004 Programação Orientada para

Objectos8

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());}

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

2003/2004 Programação Orientada para

Objectos9

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; }

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

2003/2004 Programação Orientada para

Objectos10

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, …

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

2003/2004 Programação Orientada para

Objectos11

Construtor por cópia

O que sucede depois de:

PilhaDeInt p1;PilhaDeInt p2 = p1;// Ou PilhaDeInt p2(p1);

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

2003/2004 Programação Orientada para

Objectos12

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.

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

2003/2004 Programação Orientada para

Objectos13

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

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

2003/2004 Programação Orientada para

Objectos14

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

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

2003/2004 Programação Orientada para

Objectos15

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!

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

2003/2004 Programação Orientada para

Objectos16

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 ==.}

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

2003/2004 Programação Orientada para

Objectos17

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 ==.}

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

2003/2004 Programação Orientada para

Objectos18

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 ==.}

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

2003/2004 Programação Orientada para

Objectos19

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 ==.}

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

2003/2004 Programação Orientada para

Objectos20

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;

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

2003/2004 Programação Orientada para

Objectos21

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.

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

2003/2004 Programação Orientada para

Objectos22

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

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

2003/2004 Programação Orientada para

Objectos23

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: …};

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

2003/2004 Programação Orientada para

Objectos24

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 ==.}

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

2003/2004 Programação Orientada para

Objectos25

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 ==.}

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

2003/2004 Programação Orientada para

Objectos26

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 ==.}

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

2003/2004 Programação Orientada para

Objectos27

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 ==.}

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

2003/2004 Programação Orientada para

Objectos28

Atribuição por cópia

O que deveria acontecer depois de:

PilhaDeInt p;

p.põe(1);p.põe(2);

p = p; Nada!

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

2003/2004 Programação Orientada para

Objectos29

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!

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

2003/2004 Programação Orientada para

Objectos30

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?

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

2003/2004 Programação Orientada para

Objectos31

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

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

2003/2004 Programação Orientada para

Objectos32

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?

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

2003/2004 Programação Orientada para

Objectos33

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

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

2003/2004 Programação Orientada para

Objectos34

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.

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

2003/2004 Programação Orientada para

Objectos35

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 ==.}

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

2003/2004 Programação Orientada para

Objectos36

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.

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

2003/2004 Programação Orientada para

Objectos37

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

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

2003/2004 Programação Orientada para

Objectos38

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