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.

Slides:



Advertisements
Apresentações semelhantes
IFTO ESTRUTURA DE DADOS AULA 05 Prof. Manoel Campos da Silva Filho
Advertisements

Aula T10 – BCC202 Listas – Parte 2 Túlio Toffolo www. decom. ufop
Programação em Java Prof. Maurício Braga
Um programa em C Bibliotecas Variáveis globais
Métodos, Parâmetros, Argumentos e Contratos
14/10/09 Uma animação possui: Início; Passo; Fim; 1.
Interação entre objetos
Copyright (c) 2003 by Valery Sklyarov and Iouliia Skliarova: DETUA, IEETA, Aveiro University, Portugal.
1. Classes 2. Membros estáticos 1.1. Palavra chave this
1 INQUÉRITOS PEDAGÓGICOS 2º Semestre 2003/2004 ANÁLISE GERAL DOS RESULTADOS OBTIDOS 1.Nº de RESPOSTAS ao inquérito 2003/2004 = (42,8%) 2.Comparação.
Ludwig Krippahl, 2008 Programação para as Ciências Experimentais 2007/8 Teórica 6.
Universidade Bandeirante de São Paulo Fundamentos da Álgebra
Crescimento Econômico Brasileiro : Uma Visão Comparada de Longo Prazo Prof. Giácomo Balbinotto Neto UFRGS.
Mais sobre classes Baseada no Livro: Deitel&Deitel - C++ How To program Cap. 7 Prentice Hall 1994 SCE 213 Programação Orientada a Objetos, ICMC - USP 2.
Funções.
Modularização: funções e procedimentos
1 Aula 5 Instâncias dinâmicas. 2003/2004 Programação Orientada para Objectos 2 Instâncias… int j = 20; int f() { int const i = 10; // … } Constante automática.
Matrizes clássicas e vectores em C++
1 Aula 4 Ponteiros. 2003/2004 Programação Orientada para Objectos 2 Instâncias de um programa C++ int i = 10; Nome: i Tipo: int Valor: 10.
Aula 10 Tipos Abstractos de Dados I. 2003/2004 Introdução à Programação 2 Flashback Lembram-se da Aula 4?
Modularização: funções e procedimentos (continuação)
1 Aula 3 Listas e iteradores (cont.). 2003/2004 Programação Orientada para Objectos 2 ListaDeInt : interface class ListaDeInt { public: typedef int Item;
Aula 8 Polimorfismo.
Metodologia de Dijkstra para desenvolvimento de ciclos
Programação Baseada em Objectos Desenho de TAD
Aula 6 Instruções de selecção e instruções condicionais.
1 Aula 7 Herança. 2003/2004 Programação Orientada para Objectos 2 Conceitos fundamentais: Herança Polimorfismo Ligação dinâmica.
Sobrecarga de nomes de rotinas Rotinas recursivas Invocação de rotinas
Aula 13 Tipos Abstractos de Dados IV. 2003/2004 Introdução à Programação 2 Estrutura global do programa (I) Construtores Inspectores.
Fases do desenvolvimento de software UML
2002/2003 Programação Orientada para Objectos 1 Aula 3 Utilização de listas Melhorando a implementação das listas e iteradores Reflexão sobre interfaces.
Classes e objetos P. O. O. Prof. Grace.
Provas de Concursos Anteriores
Algoritmos e linguagens de programação 1 (aula 05)
Bolsas Vera Crevelin OBS: Nos slides disponíveis clique sobre o ícone de informação para visualizar mais fotos das bolsas.
Classes Revisando: –Forma de implementação de estruturas específicas –Atributos (grupos de dados) –Métodos (conjuntos de procedimentos)
MECÂNICA - DINÂMICA Cinemática Plana de um Corpo Rígido Cap. 16.
Cinética Plana de uma Partícula: Força e Aceleração Cap. 13
1 programa dados Utilização de ficheiros externos A maneira mais simples de escrever para um ficheiro externo é redireccionar a saída de um programa: em.
1 programa dados Utilização de ficheiros externos A maneira mais simples de escrever para um ficheiro externo é redireccionar a saída de um programa: em.
Informática e Computação Estrutura de Repetição aula 13
Exercício 1 Faça um programa que receba como entrada o nome e o salário de um funcionário de uma empresa e que calcule o novo valor do salário do.
Aula 07.
1 António Arnaut Duarte. 2 Sumário: primeiros passos;primeiros passos formatar fundo;formatar fundo configurar apresentação;configurar apresentação animação.
Funções Universidade Federal de Ouro Preto - UFOP
Introdução a Programação COM 100
Coordenação Geral de Ensino da Faculdade
Linguagem de Programação II
É u m e l e m e n t o f u n d a m e n t a l
7 Arrays.
Procedural vs. OO (Figuras Geométricas: Área do triângulo)
SairPróximo Itens de Seleção Probabilidades e Combinatória Cálculo Combinatório. Problemas de Contagem. ITENS DE SELEÇÃO DOS EXAMES NACIONAIS E TESTES.
Aula 6 - Estruturas de Controle
MATRICIAL CONSULTORIA LTDA. PREFEITURA MUNICIPAL DE GARIBALDI 23/10/ : ATENÇÃO Os locais descritos nas planilhas anexas não correspondem ao total.
Curso: Cerimonial, Protocolo e Eventos
Máquina de Turing Universal
2002/2003 Programação Orientada para Objectos 1 Aula 6 Classes que reservam recursos externos Problemas comuns Construtores e destrutores Construção por.
1 Prof. Humberto Pinheiro, Ph.D SISTEMAS DE MODULAÇÃO DPEE-CT-UFSM Modulação Geométrica Conversores Multiníveis Trifásicos com Diodo de Grampeamento.
Informática e Computação Estrutura de Repetição aula 12
Medidas de tendência central e de dispersão
FACULDADE DE CIÊNCIAS SOCIAIS E TECNOLÓGICAS Tecnologia em Redes de Computadores Algoritmos e linguagens de programação 1 (aula 07) Prof. Alessandro Bernardo.
Introdução à Linguagem C
2002/2003 Programação Orientada para Objectos 1 Aula 2 Noção de lista e de iterador Operações com listas e iteradores Classes embutidas.
Revisão Luis Antonio Tavares
CES-10 INTRODUÇÃO À COMPUTAÇÃO Aulas Práticas – 2014 Capítulo IX Subprogramação e Recursividade.
1Unidade – Estrutura Condicional CASE Algoritmos e Linguagens de Programação Estrutura Condicional CASE Faculdade INED – Abril 2007 Prof. Edwar.
VETORES AULA 01 Roteiro da aula Referência ao Programa: Estrutura de Dados.  Variáveis Compostas homogenias   Objetivo: apresentar VETOR.
CES-11 ALGORITMOS E ESTRUTURAS DE DADOS Aulas Práticas
Ponteiros Parte III.
CES-11 ALGORITMOS E ESTRUTURAS DE DADOS Aulas Práticas
Transcrição da apresentação:

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 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ê?

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)

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!

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

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)

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

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

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

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&

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&

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&

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&

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&

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.

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&

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&

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

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

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

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

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&

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&

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&

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&

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&

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&

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&

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&

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

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

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

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

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.

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

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

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

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

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

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

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…

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&

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

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

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

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

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

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!

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

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…

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!

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

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

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

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

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)

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.

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!

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

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.

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

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

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

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

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

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&

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

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!

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

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&

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

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.

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

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

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

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

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!

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

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

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

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

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

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&

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

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&

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&

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&

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

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&

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&

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

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

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!

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

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?

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

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.

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

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!

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

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