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

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

Aula 11 Tipos Abstractos de Dados II. 2003/2004 Introdução à Programação 2 Estrutura global do programa #include using namespace std; int mdc(int const.

Apresentações semelhantes


Apresentação em tema: "Aula 11 Tipos Abstractos de Dados II. 2003/2004 Introdução à Programação 2 Estrutura global do programa #include using namespace std; int mdc(int const."— Transcrição da apresentação:

1 Aula 11 Tipos Abstractos de Dados II

2 2003/2004 Introdução à Programação 2 Estrutura global do programa #include using namespace std; int mdc(int const m, int const n) { … } class Racional { … }; Racional::Racional(int const n) { … } Racional::Racional(int const n, int const d) { … } void Racional::escreve() { … } Racional Racional::somaCom(Racional const& r2) { … } void Racional::lê() { … } void Racional::reduz() { … } bool Racional::cumpreInvariante() { … } int main() { … } Diferente! Porquê?

3 2003/2004 Introdução à Programação 3 TAD Racional (I) /** Representa números 0 < denominador mdc( numerador, denominador ) = 1. */ class Racional { public: /** Constrói racional com valor * this = n. */ Racional(int const n = 0); /** Constrói racional correspondente a n / d * this = n / d. */ Racional(int const n, int const d); /** Escreve um racional no ecrã no formato de uma cout. fail () ou cout contém n/d (ou simplesmente n, se d = 1) em que n e d são os valores de numerador e denominador. */ void escreve(); (continua)

4 2003/2004 Introdução à Programação 4 TAD Racional (II) (continuação) /** Devolve a soma de dois somaDe = * this + r2. */ Racional somaCom(Racional const& r2); /** Lê do teclado um racional, na forma de dois inteiros * this = Se cin. good () cin tem dois inteiros n e d disponíveis para leitura, com d <> 0, então * this = n/d cin. fail (), senão * this = r cin. fail (). */ void lê(); (continua) Diferente!

5 2003/2004 Introdução à Programação 5 TAD Racional (III) (continuação) private: /** Indica se a CIC se cumpreInvariante = 0 < denominador mdc( numerador, denominador ) = 1. */ bool cumpreInvariante(); /** Reduz a fracção que representa o denominador 0 *this = denominador 0 mdc( numerador, denominador ) = 1 * this = r. */ void reduz(); int numerador; int denominador; };

6 2003/2004 Introdução à Programação 6 Traçado int main() { // Ler fracções: cout << "Introduza duas fracções (numer … Racional r1, r2; r1.lê(); r2.lê(); if(cin.fail()) { cout << "Opps! A leitura dos racion … return 1; } (continua)

7 2003/2004 Introdução à Programação 7 Traçado int main() { // Ler fracções: cout << "Introduza duas fracções (numer … Racional r1, r2; r1.lê(); r2.lê(); if(cin.fail()) { cout << "Opps! A leitura dos racion … return 1; } (continua) main()

8 2003/2004 Introdução à Programação 8 Traçado int main() { // Ler fracções: cout << "Introduza duas fracções (numer … Racional r1, r2; r1.lê(); r2.lê(); if(cin.fail()) { cout << "Opps! A leitura dos racion … return 1; } (continua) Introduza … main()

9 2003/2004 Introdução à Programação 9 Traçado int main() { // Ler fracções: cout << "Introduza duas fracções (numer … Racional r1, r2; r1.lê(); r2.lê(); if(cin.fail()) { cout << "Opps! A leitura dos racion … return 1; } (continua) Introduza … main() r1 : Racional

10 2003/2004 Introdução à Programação 10 Traçado Racional::Racional(int const n) : numerador(n), denominador(1) { assert(cumpreInvariante()); } Introduza … Racional:: Racional() main() r1 : Racional n : int {frozen} 0 *this : Racional&

11 2003/2004 Introdução à Programação 11 Traçado Racional::Racional(int const n) : numerador(n), denominador(1) { assert(cumpreInvariante()); } Introduza … Racional:: Racional() main() r1 : Racional n : int {frozen} 0 numerador : int 0 *this : Racional&

12 2003/2004 Introdução à Programação 12 Traçado Racional::Racional(int const n) : numerador(n), denominador(1) { assert(cumpreInvariante()); } Introduza … Racional:: Racional() main() r1 : Racional n : int {frozen} 0 numerador : int 0 denominador : int 1 *this : Racional&

13 2003/2004 Introdução à Programação 13 Traçado Racional::Racional(int const n) : numerador(n), denominador(1) { assert(cumpreInvariante()); } Introduza … Racional:: Racional() main() r1 : Racional n : int {frozen} 0 numerador : int 0 denominador : int 1 *this : Racional&

14 2003/2004 Introdução à Programação 14 Traçado bool Racional::cumpreInvariante() { return 0 < denominador and mdc(numerador, denominador) == 1; } Introduza … Racional:: cumpreInvariante() main() r1 : Racional numerador : int 0 denominador : int 1 *this : Racional&

15 2003/2004 Introdução à Programação 15 Traçado bool Racional::cumpreInvariante() { return 0 < denominador and mdc(numerador, denominador) == 1; } Introduza … Racional:: cumpreInvariante() main() r1 : Racional numerador : int 0 denominador : int 1 *this : Racional& Devolve verdadeiro.

16 2003/2004 Introdução à Programação 16 Traçado Racional::Racional(int const n) : numerador(n), denominador(1) { assert(cumpreInvariante()); } Introduza … Racional:: Racional() main() r1 : Racional n : int 0 numerador : int 0 denominador : int 1 *this : Racional&

17 2003/2004 Introdução à Programação 17 Traçado Racional::Racional(int const n) : numerador(n), denominador(1) { assert(cumpreInvariante()); } Introduza … Racional:: Racional() main() r1 : Racional n : int 0 numerador : int 0 denominador : int 1 *this : Racional&

18 2003/2004 Introdução à Programação 18 Traçado int main() { // Ler fracções: cout << "Introduza duas fracções (numer … Racional r1, r2; r1.lê(); r2.lê(); if(cin.fail()) { cout << "Opps! A leitura dos racion … return 1; } (continua) Introduza … main() r1 : Racional numerador : int 0 denominador : int 1 r2 : Racional numerador : int 0 denominador : int 1

19 2003/2004 Introdução à Programação 19 Traçado int main() { // Ler fracções: cout << "Introduza duas fracções (numer … Racional r1, r2; r1.lê(); r2.lê(); if(cin.fail()) { cout << "Opps! A leitura dos racion … return 1; } (continua) Introduza … main() r1 : Racional numerador = 0 denominador = 1 r2 : Racional numerador = 0 denominador = 1

20 2003/2004 Introdução à Programação 20 Traçado int main() { // Ler fracções: cout << "Introduza duas fracções (numer … Racional r1, r2; r1.lê(); r2.lê(); if(cin.fail()) { cout << "Opps! A leitura dos racion … return 1; } (continua) Introduza … main() r1 : Racional numerador = 0 denominador = 1 r2 : Racional numerador = 0 denominador = 1

21 2003/2004 Introdução à Programação 21 Traçado int main() { // Ler fracções: cout << "Introduza duas fracções (numer … Racional r1, r2; r1.lê(); r2.lê(); if(cin.fail()) { cout << "Opps! A leitura dos racion … return 1; } (continua) Introduza … main() r1 : Racional numerador = 0 denominador = 1 r2 : Racional numerador = 0 denominador = 1

22 2003/2004 Introdução à Programação 22 Traçado void Racional::lê() { int n, d; cin >> n >> d; if(not cin.fail()) if(d == 0) cin.setstate(ios_base::failbit); else { if(d < 0) { numerador = -n; denominador = -d; } else { numerador = n; denominador = d; } reduz(); } Introduza … main() r1 : Racional numerador = 0 denominador = 1 r2 : Racional numerador = 0 denominador = 1 Racional::lê() Sem asserções, para encurtar. *this : Racional&

23 2003/2004 Introdução à Programação 23 Traçado void Racional::lê() { int n, d; cin >> n >> d; if(not cin.fail()) if(d == 0) cin.setstate(ios_base::failbit); else { if(d < 0) { numerador = -n; denominador = -d; } else { numerador = n; denominador = d; } reduz(); } Introduza … main() r1 : Racional numerador = 0 denominador = 1 r2 : Racional numerador = 0 denominador = 1 Racional::lê() n : int ? d : int ? *this : Racional&

24 2003/2004 Introdução à Programação 24 Traçado void Racional::lê() { int n, d; cin >> n >> d; if(not cin.fail()) if(d == 0) cin.setstate(ios_base::failbit); else { if(d < 0) { numerador = -n; denominador = -d; } else { numerador = n; denominador = d; } reduz(); } Introduza … main() r1 : Racional numerador = 0 denominador = 1 r2 : Racional numerador = 0 denominador = 1 Racional::lê() n : int ? d : int ? n : int 6 d : int 9 *this : Racional&

25 2003/2004 Introdução à Programação 25 Traçado void Racional::lê() { int n, d; cin >> n >> d; if(not cin.fail()) if(d == 0) cin.setstate(ios_base::failbit); else { if(d < 0) { numerador = -n; denominador = -d; } else { numerador = n; denominador = d; } reduz(); } Introduza … main() r1 : Racional numerador = 0 denominador = 1 r2 : Racional numerador = 0 denominador = 1 Racional::lê() n : int 6 d : int 9 *this : Racional&

26 2003/2004 Introdução à Programação 26 Traçado void Racional::lê() { int n, d; cin >> n >> d; if(not cin.fail()) if(d == 0) cin.setstate(ios_base::failbit); else { if(d < 0) { numerador = -n; denominador = -d; } else { numerador = n; denominador = d; } reduz(); } Introduza … main() r1 : Racional numerador = 0 denominador = 1 r2 : Racional numerador = 0 denominador = 1 Racional::lê() n : int 6 d : int 9 *this : Racional&

27 2003/2004 Introdução à Programação 27 Traçado void Racional::lê() { int n, d; cin >> n >> d; if(not cin.fail()) if(d == 0) cin.setstate(ios_base::failbit); else { if(d < 0) { numerador = -n; denominador = -d; } else { numerador = n; denominador = d; } reduz(); } Introduza … main() r1 : Racional numerador = 0 denominador = 1 r2 : Racional numerador = 0 denominador = 1 Racional::lê() n : int 6 d : int 9 *this : Racional&

28 2003/2004 Introdução à Programação 28 Traçado void Racional::lê() { int n, d; cin >> n >> d; if(not cin.fail()) if(d == 0) cin.setstate(ios_base::failbit); else { if(d < 0) { numerador = -n; denominador = -d; } else { numerador = n; denominador = d; } reduz(); } Introduza … main() r1 : Racional numerador = 0 denominador = 1 r2 : Racional numerador = 0 denominador = 1 Racional::lê() n : int 6 d : int 9 *this : Racional&

29 2003/2004 Introdução à Programação 29 Traçado void Racional::lê() { int n, d; cin >> n >> d; if(not cin.fail()) if(d == 0) cin.setstate(ios_base::failbit); else { if(d < 0) { numerador = -n; denominador = -d; } else { numerador = n; denominador = d; } reduz(); } Introduza … main() r1 : Racional numerador = 0 denominador = 1 r2 : Racional numerador = 0 denominador = 1 Racional::lê() n : int 6 d : int 9 *this : Racional&

30 2003/2004 Introdução à Programação 30 Traçado void Racional::lê() { int n, d; cin >> n >> d; if(not cin.fail()) if(d == 0) cin.setstate(ios_base::failbit); else { if(d < 0) { numerador = -n; denominador = -d; } else { numerador = n; denominador = d; } reduz(); } Introduza … main() r1 : Racional numerador = 0 denominador = 1 r2 : Racional numerador = 0 denominador = 1 Racional::lê() n : int 6 d : int 9 *this : Racional& r1 : Racional numerador = 6 denominador = 1

31 2003/2004 Introdução à Programação 31 Traçado void Racional::lê() { int n, d; cin >> n >> d; if(not cin.fail()) if(d == 0) cin.setstate(ios_base::failbit); else { if(d < 0) { numerador = -n; denominador = -d; } else { numerador = n; denominador = d; } reduz(); } Introduza … main() r2 : Racional numerador = 0 denominador = 1 Racional::lê() n : int 6 d : int 9 *this : Racional& r1 : Racional numerador = 6 denominador = 1 r1 : Racional numerador = 6 denominador = 9

32 2003/2004 Introdução à Programação 32 Traçado void Racional::lê() { int n, d; cin >> n >> d; if(not cin.fail()) if(d == 0) cin.setstate(ios_base::failbit); else { if(d < 0) { numerador = -n; denominador = -d; } else { numerador = n; denominador = d; } reduz(); } Introduza … main() r2 : Racional numerador = 0 denominador = 1 Racional::lê() n : int 6 d : int 9 *this : Racional& r1 : Racional numerador = 6 denominador = 1 r1 : Racional numerador = 6 denominador = 9

33 2003/2004 Introdução à Programação 33 Traçado void Racional::reduz() { assert(denominador != 0); int const divisor = mdc(numerador, denominador); numerador /= divisor; denominador /= divisor; assert(denominador != 0); assert(mdc(numerador, denominador) == 1); } Introduza … main() r2 : Racional numerador = 0 denominador = 1 Racional::reduz() *this : Racional& r1 : Racional numerador = 6 denominador = 1 r1 : Racional numerador = 6 denominador = 9

34 2003/2004 Introdução à Programação 34 Traçado void Racional::reduz() { assert(denominador != 0); int const divisor = mdc(numerador, denominador); numerador /= divisor; denominador /= divisor; assert(denominador != 0); assert(mdc(numerador, denominador) == 1); } Introduza … main() r2 : Racional numerador = 0 denominador = 1 Racional::reduz() *this : Racional& r1 : Racional numerador = 6 denominador = 1 r1 : Racional numerador = 6 denominador = 9 divisor : int {frozen} 3 Ignoram-se asserções, para encurtar.

35 2003/2004 Introdução à Programação 35 Traçado void Racional::reduz() { assert(denominador != 0); int const divisor = mdc(numerador, denominador); numerador /= divisor; denominador /= divisor; assert(denominador != 0); assert(mdc(numerador, denominador) == 1); } Introduza … main() r2 : Racional numerador = 0 denominador = 1 Racional::reduz() *this : Racional& r1 : Racional numerador = 6 denominador = 1 r1 : Racional numerador = 6 denominador = 9 divisor : int {frozen} 3 r1 : Racional numerador = 2 denominador = 9

36 2003/2004 Introdução à Programação 36 Traçado void Racional::reduz() { assert(denominador != 0); int const divisor = mdc(numerador, denominador); numerador /= divisor; denominador /= divisor; assert(denominador != 0); assert(mdc(numerador, denominador) == 1); } Introduza … main() r2 : Racional numerador = 0 denominador = 1 Racional::reduz() *this : Racional& r1 : Racional numerador = 2 denominador = 9 divisor : int {frozen} 3 r1 : Racional numerador = 2 denominador = 3

37 2003/2004 Introdução à Programação 37 Traçado void Racional::reduz() { assert(denominador != 0); int const divisor = mdc(numerador, denominador); numerador /= divisor; denominador /= divisor; assert(denominador != 0); assert(mdc(numerador, denominador) == 1); } Introduza … main() r2 : Racional numerador = 0 denominador = 1 Racional::reduz() *this : Racional& divisor : int {frozen} 3 r1 : Racional numerador = 2 denominador = 3

38 2003/2004 Introdução à Programação 38 Traçado void Racional::lê() { int n, d; cin >> n >> d; if(not cin.fail()) if(d == 0) cin.setstate(ios_base::failbit); else { if(d < 0) { numerador = -n; denominador = -d; } else { numerador = n; denominador = d; } reduz(); } Introduza … main() r2 : Racional numerador = 0 denominador = 1 Racional::lê() n : int 6 d : int 9 *this : Racional& r1 : Racional numerador = 6 denominador = 1 r1 : Racional numerador = 2 denominador = 3

39 2003/2004 Introdução à Programação 39 Traçado int main() { // Ler fracções: cout << "Introduza duas fracções (numer … Racional r1, r2; r1.lê(); r2.lê(); if(cin.fail()) { cout << "Opps! A leitura dos racion … return 1; } (continua) Introduza … main() r1 : Racional numerador = 2 denominador = 3 r2 : Racional numerador = 0 denominador = 1 r2 : Racional numerador = 7 denominador = 3

40 2003/2004 Introdução à Programação 40 Traçado int main() { // Ler fracções: cout << "Introduza duas fracções (numer … Racional r1, r2; r1.lê(); r2.lê(); if(cin.fail()) { cout << "Opps! A leitura dos racion … return 1; } (continua) Introduza … main() r1 : Racional numerador = 2 denominador = 3 r2 : Racional numerador = 7 denominador = 3

41 2003/2004 Introdução à Programação 41 Traçado (continuação) // Calcular racional soma: Racional r = r1.somaCom(r2); // Escrever resultado: cout << "A soma de "; r1.escreve(); cout << " com "; r2.escreve(); cout << " é "; r.escreve(); cout << '.' << endl; } Introduza … main() r1 : Racional numerador = 2 denominador = 3 r2 : Racional numerador = 7 denominador = 3 Medonho…

42 2003/2004 Introdução à Programação 42 Traçado Racional Racional::somaCom(Racional const& r2) { assert(cumpreInvariante()); assert(r2.cumpreInvariante()); Racional r; r.numerador = numerador * r2.denominador + r2.numerador * denominador; r.denominador = denominador * r2.denominador; r.reduz(); assert(cumpreInvariante()); assert(r.cumpreInvariante()); return r; } Introduza … main() r2 : Racional numerador = 7 denominador = 3 Racional::somaCom() *this : Racional& r1 : Racional numerador = 6 denominador = 1 r1 : Racional numerador = 2 denominador = 3 r2 : Racional const&

43 2003/2004 Introdução à Programação 43 Traçado Racional Racional::somaCom(Racional const& r2) { assert(cumpreInvariante()); assert(r2.cumpreInvariante()); Racional r; r.numerador = numerador * r2.denominador + r2.numerador * denominador; r.denominador = denominador * r2.denominador; r.reduz(); assert(cumpreInvariante()); assert(r.cumpreInvariante()); return r; } Introduza … main() r2 : Racional numerador = 7 denominador = 3 Racional::somaCom() *this : Racional& r1 : Racional numerador = 6 denominador = 1 r1 : Racional numerador = 2 denominador = 3 r2 : Racional const& r : Racional numerador = 0 denominador = 1

44 2003/2004 Introdução à Programação 44 Traçado Racional Racional::somaCom(Racional const& r2) { assert(cumpreInvariante()); assert(r2.cumpreInvariante()); Racional r; r.numerador = numerador * r2.denominador + r2.numerador * denominador; r.denominador = denominador * r2.denominador; r.reduz(); assert(cumpreInvariante()); assert(r.cumpreInvariante()); return r; } Introduza … main() r2 : Racional numerador = 7 denominador = 3 Racional::somaCom() *this : Racional& r1 : Racional numerador = 6 denominador = 1 r1 : Racional numerador = 2 denominador = 3 r2 : Racional const& r : Racional numerador = 0 denominador = 1 r : Racional numerador = 27 denominador = 1

45 2003/2004 Introdução à Programação 45 Traçado Racional Racional::somaCom(Racional const& r2) { assert(cumpreInvariante()); assert(r2.cumpreInvariante()); Racional r; r.numerador = numerador * r2.denominador + r2.numerador * denominador; r.denominador = denominador * r2.denominador; r.reduz(); assert(cumpreInvariante()); assert(r.cumpreInvariante()); return r; } Introduza … main() r2 : Racional numerador = 7 denominador = 3 Racional::somaCom() *this : Racional& r1 : Racional numerador = 6 denominador = 1 r1 : Racional numerador = 2 denominador = 3 r2 : Racional const& r : Racional numerador = 27 denominador = 1 r : Racional numerador = 27 denominador = 9

46 2003/2004 Introdução à Programação 46 Traçado Racional Racional::somaCom(Racional const& r2) { assert(cumpreInvariante()); assert(r2.cumpreInvariante()); Racional r; r.numerador = numerador * r2.denominador + r2.numerador * denominador; r.denominador = denominador * r2.denominador; r.reduz(); assert(cumpreInvariante()); assert(r.cumpreInvariante()); return r; } Introduza … main() r2 : Racional numerador = 7 denominador = 3 Racional::somaCom() *this : Racional& r1 : Racional numerador = 6 denominador = 1 r1 : Racional numerador = 2 denominador = 3 r2 : Racional const& r : Racional numerador = 27 denominador = 9 Qual será a instância implícita? r : Racional numerador = 3 denominador = 1

47 2003/2004 Introdução à Programação 47 Traçado Racional Racional::somaCom(Racional const& r2) { assert(cumpreInvariante()); assert(r2.cumpreInvariante()); Racional r; r.numerador = numerador * r2.denominador + r2.numerador * denominador; r.denominador = denominador * r2.denominador; r.reduz(); assert(cumpreInvariante()); assert(r.cumpreInvariante()); return r; } Introduza … main() r2 : Racional numerador = 7 denominador = 3 Racional::somaCom() *this : Racional& r1 : Racional numerador = 6 denominador = 1 r1 : Racional numerador = 2 denominador = 3 r2 : Racional const& r : Racional numerador = 3 denominador = 1

48 2003/2004 Introdução à Programação 48 Traçado (continuação) // Calcular racional soma: Racional r = r1.somaCom(r2); // Escrever resultado: cout << "A soma de "; r1.escreve(); cout << " com "; r2.escreve(); cout << " é "; r.escreve(); cout << '.' << endl; } Introduza … main() r1 : Racional numerador = 2 denominador = 3 r2 : Racional numerador = 7 denominador = 3 r : Racional numerador = 3 denominador = 1 É igual ao racional devolvido por Racional::somaCom(), mas não é a mesma instância!

49 2003/2004 Introdução à Programação 49 Traçado Etc…..

50 2003/2004 Introdução à Programação 50 O nosso objectivo #include using namespace std; … int main() { cout << "Introduza duas fracções (numerador denominador): "; Racional r1, r2; cin >> r1 >> r2; if(cin.fail()) { cout << "Opps! A leitura dos racionais falhou!" << endl; return 1; } Racional r = r1 + r2; cout << "A soma de " << r1 << " com " << r2 << " é " << r << '.' << endl; } Hoje ficaremos mais próximos…

51 2003/2004 Introdução à Programação 51 Sobrecarga de operadores Sobrecarga de rotinas possível: int soma() int soma(int const a) int soma(int const a, int const b) Sobrecarga de operadores também!

52 2003/2004 Introdução à Programação 52 Operação Racional::operator+() /** … */ class Racional { public: … /** Devolve a soma de dois somaDe = * this + r2. */ Racional operator+(Racional const& r2); … private: … };

53 2003/2004 Introdução à Programação 53 Método Racional::operator+() Racional Racional::operator+(Racional const& r2) { assert(cumpreInvariante()); assert(r2.cumpreInvariante()); Racional r; r.numerador = numerador * r2.denominador + r2.numerador * denominador; r.denominador = denominador * r2.denominador; r.reduz(); assert(cumpreInvariante()); assert(r.cumpreInvariante()); return r; }

54 2003/2004 Introdução à Programação 54 Função main() int main() { … // Calcular racional soma: Racional r = r1.operator+(r2); … }

55 2003/2004 Introdução à Programação 55 Função main() int main() { … // Calcular racional soma: Racional r = r1 + r2; … }

56 2003/2004 Introdução à Programação 56 Sobrecarga de operadores Como membro de classe: Primeiro operando é instância implícita! Outros operandos são passados como argumentos Racional Racional::operator+(Racional const& r2) Como rotina livre: Todos os operandos passados como argumentos Racional operator+(Racional const& r1, Racional const& r2)

57 2003/2004 Introdução à Programação 57 Operadores a sobrecarregar Aritméticos: Binários: *, /, + e - Unários: + e - Relacionais: e >= Igualdade e diferença: == e != Incrementação: Prefixo: ++ e -- Sufixo: ++ e -- Especiais de atribuição: *=, /=, += e -= Vamos começar por aqui.

58 2003/2004 Introdução à Programação 58 Um problema Que devolve o operador ++ prefixo? Exemplo: int i = 0; ++(++i); cout << i << endl; 2 Tem de resultar no próprio i, e não numa cópia. É um exemplo do que é possível fazer, e não uma sugestão de que é recomendável!

59 2003/2004 Introdução à Programação 59 Um caso bicudo int main() { int i = 0; ++(++i); cout << i << endl; }

60 2003/2004 Introdução à Programação 60 E um regresso às origens void incrementa(int& v) { v = v + 1; } int main() { int i = 0; incrementa(incrementa(i)); cout << i << endl; } Invocação impossível! incrementa() não devolve nada.

61 2003/2004 Introdução à Programação 61 Correcção… int incrementa(int& v) { v = v + 1; return v; } int main() { int i = 0; incrementa(incrementa(i)); cout << i << endl; }

62 2003/2004 Introdução à Programação 62 Funcionará? int incrementa(int& v) { v = v + 1; return v; } int main() { int i = 0; incrementa(incrementa(i)); cout << i << endl; }

63 2003/2004 Introdução à Programação 63 Funcionará? int incrementa(int& v) { v = v + 1; return v; } int main() { int i = 0; incrementa(incrementa(i)); cout << i << endl; } main()

64 2003/2004 Introdução à Programação 64 Funcionará? int incrementa(int& v) { v = v + 1; return v; } int main() { int i = 0; incrementa(incrementa(i)); cout << i << endl; } main() i : int 0

65 2003/2004 Introdução à Programação 65 Funcionará? int incrementa(int& v) { v = v + 1; return v; } int main() { int i = 0; incrementa(incrementa(i)); cout << i << endl; } main() i : int 0

66 2003/2004 Introdução à Programação 66 Funcionará? int incrementa(int& v) { v = v + 1; return v; } int main() { int i = 0; incrementa(incrementa(i)); cout << i << endl; } main() i : int 0 incrementa() v : int&

67 2003/2004 Introdução à Programação 67 Funcionará? int incrementa(int& v) { v = v + 1; return v; } int main() { int i = 0; incrementa(incrementa(i)); cout << i << endl; } main() i : int 0 incrementa() v : int& i : int 1

68 2003/2004 Introdução à Programação 68 Funcionará? int incrementa(int& v) { v = v + 1; return v; } int main() { int i = 0; incrementa(incrementa(i)); cout << i << endl; } main() incrementa() v : int& i : int 1 : int 1 Valor devolvido é cópia de v, i.e., é cópia de i. É instância temporária!

69 2003/2004 Introdução à Programação 69 Funcionará? int incrementa(int& v) { v = v + 1; return v; } int main() { int i = 0; incrementa(incrementa(i)); cout << i << endl; } main() i : int 1 : int 1

70 2003/2004 Introdução à Programação 70 Funcionará? int incrementa(int& v) { v = v + 1; return v; } int main() { int i = 0; incrementa(incrementa(i)); cout << i << endl; } main() i : int 1 : int 1 incrementa() v : int&

71 2003/2004 Introdução à Programação 71 Funcionará? int incrementa(int& v) { v = v + 1; return v; } int main() { int i = 0; incrementa(incrementa(i)); cout << i << endl; } main() i : int 1 : int 1 incrementa() v : int& : int 2

72 2003/2004 Introdução à Programação 72 Funcionará? int incrementa(int& v) { v = v + 1; return v; } int main() { int i = 0; incrementa(incrementa(i)); cout << i << endl; } main() i : int 1 incrementa() v : int& : int 2 2 Valor devolvido é cópia de v, i.e., é cópia da cópia alterada de i.

73 2003/2004 Introdução à Programação 73 Funcionará? int incrementa(int& v) { v = v + 1; return v; } int main() { int i = 0; incrementa(incrementa(i)); cout << i << endl; } main() i : int 1 : int 2 2

74 2003/2004 Introdução à Programação 74 Funcionará? int incrementa(int& v) { v = v + 1; return v; } int main() { int i = 0; incrementa(incrementa(i)); cout << i << endl; } main() i : int 1 1

75 2003/2004 Introdução à Programação 75 Funcionará? int incrementa(int& v) { v = v + 1; return v; } int main() { int i = 0; incrementa(incrementa(i)); cout << i << endl; } main() i : int 1 1

76 2003/2004 Introdução à Programação 76 Moral da história Segunda incrementação falhou Ou melhor, incrementou cópia Porque devolução faz-se por valor Necessário devolver por referência

77 2003/2004 Introdução à Programação 77 Em abono da verdade… … o código nem sequer compila! C++ proíbe referência (não constante) para instância temporária!

78 2003/2004 Introdução à Programação 78 Outra correcção… int& incrementa(int& v) { v = v + 1; return v; } int main() { int i = 0; incrementa(incrementa(i)); cout << i << endl; }

79 2003/2004 Introdução à Programação 79 E agora? int& incrementa(int& v) { v = v + 1; return v; } int main() { int i = 0; incrementa(incrementa(i)); cout << i << endl; }

80 2003/2004 Introdução à Programação 80 E agora? int& incrementa(int& v) { v = v + 1; return v; } int main() { int i = 0; incrementa(incrementa(i)); cout << i << endl; } main()

81 2003/2004 Introdução à Programação 81 E agora? int& incrementa(int& v) { v = v + 1; return v; } int main() { int i = 0; incrementa(incrementa(i)); cout << i << endl; } main() i : int 0

82 2003/2004 Introdução à Programação 82 E agora? int& incrementa(int& v) { v = v + 1; return v; } int main() { int i = 0; incrementa(incrementa(i)); cout << i << endl; } main() i : int 0

83 2003/2004 Introdução à Programação 83 E agora? int& incrementa(int& v) { v = v + 1; return v; } int main() { int i = 0; incrementa(incrementa(i)); cout << i << endl; } main() i : int 0 incrementa() v : int&

84 2003/2004 Introdução à Programação 84 E agora? int& incrementa(int& v) { v = v + 1; return v; } int main() { int i = 0; incrementa(incrementa(i)); cout << i << endl; } main() i : int 0 incrementa() v : int& i : int 1

85 2003/2004 Introdução à Programação 85 E agora? int& incrementa(int& v) { v = v + 1; return v; } int main() { int i = 0; incrementa(incrementa(i)); cout << i << endl; } main() incrementa() v : int& i : int 1 : int&

86 2003/2004 Introdução à Programação 86 E agora? int& incrementa(int& v) { v = v + 1; return v; } int main() { int i = 0; incrementa(incrementa(i)); cout << i << endl; } main() i : int 1 : int&

87 2003/2004 Introdução à Programação 87 E agora? int& incrementa(int& v) { v = v + 1; return v; } int main() { int i = 0; incrementa(incrementa(i)); cout << i << endl; } main() i : int 1 incrementa() v : int& : int&

88 2003/2004 Introdução à Programação 88 E agora? int& incrementa(int& v) { v = v + 1; return v; } int main() { int i = 0; incrementa(incrementa(i)); cout << i << endl; } main() i : int 1 incrementa() v : int& : int& i : int 2

89 2003/2004 Introdução à Programação 89 E agora? int& incrementa(int& v) { v = v + 1; return v; } int main() { int i = 0; incrementa(incrementa(i)); cout << i << endl; } main() i : int 2 incrementa() v : int& : int&

90 2003/2004 Introdução à Programação 90 E agora? int& incrementa(int& v) { v = v + 1; return v; } int main() { int i = 0; incrementa(incrementa(i)); cout << i << endl; } main() i : int 2 : int&

91 2003/2004 Introdução à Programação 91 E agora? int& incrementa(int& v) { v = v + 1; return v; } int main() { int i = 0; incrementa(incrementa(i)); cout << i << endl; } main() i : int 2 2

92 2003/2004 Introdução à Programação 92 E agora? int& incrementa(int& v) { v = v + 1; return v; } int main() { int i = 0; incrementa(incrementa(i)); cout << i << endl; } main() i : int 2 2

93 2003/2004 Introdução à Programação 93 Finalmente… sobrecarga! int& operator++(int& v) { v = v + 1; return v; } int main() { int i = 0; ++(++i); cout << i << endl; } Era doce… Não se pode redefinir os operadores dos tipos básicos! Mas para um TAD pode-se sobrecarregar!

94 2003/2004 Introdução à Programação 94 Operação Racional::operator++() /** … */ class Racional { public: … /** Incrementa o *this = operator++ = ? *this = r + 1. */ Racional& operator++(); … private: … };

95 2003/2004 Introdução à Programação 95 Método Racional::operator++() Racional& Racional::operator++() { assert(cumpreInvariante()); numerador += denominador; assert(cumpreInvariante()); return ?; } Porque não é necessário reduzir a fracção? Os TAD devem ter comportamente semelhante aos tipos básicos. Por isso, devia-se devolver o racional incrementado. Como?

96 2003/2004 Introdução à Programação 96 Método Racional::operator++() Racional& Racional::operator++() { assert(cumpreInvariante()); numerador += denominador; assert(cumpreInvariante()); return *this; }

97 2003/2004 Introdução à Programação 97 Operação Racional::operator++() /** … */ class Racional { public: … /** Incrementa o *this = operator++ *this *this = r + 1. */ Racional& operator++(); … private: … }; O que se devolve é a instância implícita ela própria, e não uma instância temporária com igual valor.

98 2003/2004 Introdução à Programação 98 Igualdade vs. identidade Duas instâncias São idênticas se forem a mesma instância São iguais se tiverem o mesmo valor Se são idênticas, são também iguais. Podem ser iguais, mas não ser idênticas

99 2003/2004 Introdução à Programação 99 Igualdade vs. identidade int cópia(int const& v) { return v; } int& mesmo(int& v) { return v; } int main() { int i = 0; mesmo(i) = 10; cópia(i) = 20; } Ok. Erro!

100 2003/2004 Introdução à Programação 100 lvalue Lvalue é uma entidade à qual se pode atribuir um valor Instâncias temporárias não são lvalues, são rvalues

101 2003/2004 Introdução à Programação 101 Aula 11: Sumário Revisões sobre a aula anterior *this como referência Construção dos atributos: lista de inicializadores Devolução por valor e por referência Noções de identidade e igualdade Diferença entre lvalue e rvalue Introdução à sobrecarga de operadores para TAD: operadores + binário e ++ prefixo


Carregar ppt "Aula 11 Tipos Abstractos de Dados II. 2003/2004 Introdução à Programação 2 Estrutura global do programa #include using namespace std; int mdc(int const."

Apresentações semelhantes


Anúncios Google