pearson education slide 1. pearson education slide 2 cap í tulo 15 criado por frederick h....
TRANSCRIPT
Pearson Education Slide 1
Pearson Education Slide 2
Capítulo 15
Criado por Frederick H. Colclough, Colorado Technical University
Polimorfismo e Funções Virtuais
Pearson Education Slide 3
Objetivos de Estudo Princípios das Funções Virtuais
Ligação Tardia Implementando Funções Virtuais Quando usar uma Função Virtual Classes Abstratas e Funções Virtuais Puras
Ponteiros e Funções Virtuais Compatibilidade de Tipo Estendida Downcasting and upcasting Como C++ implementa Funções Virtuais
Pearson Education Slide 4
Princípios de Funções Virtuais Polimorfismo
Associação de muitos significados à uma função
Funções virtuais fornecem essa capacidade Princípio fundamental da Programação
Orientadaa Objetos!
Virtual Existe na ‘essência’ porém não de fato
Função virtual Pode ser ‘usada’ antes de ser ‘definida’
Pearson Education Slide 5
Exemplo: Figuras Melhor ilustrado com exemplos: Classes para vários tipos de figuras
Retângulos, círculos, ovais, etc. Cada figura é um objeto de uma classe
diferente Retângulo: altura, largura, ponto central Círculo: ponto central e raio
Todas derivam da classe-pai: Figura Necessita da Função: desenho()
Diferentes instruções para cada figura
Pearson Education Slide 6
Exemplo 2: Figuras Cada classe necessita de uma função desenho()
diferente Pode ser chamada ‘desenho’ em cada classe,
assim:Retêngulo r;Círculo c;r.desenho(); // Chama Retângulo da classe desenhoc.desenho(); // Chama Círculo da classe desenho
Nada de novo até aqui…
Pearson Education Slide 7
Exemplo Figuras : centro( ) Classe-pai Figura contém funções que
se aplicam à ‘todas’ as figuras:centro(): move a figura para o centro da tela
Primeiro apaga para então redesenhar Então Figura::centro() usa a função
desenho()para redesenhar
Complicações! Qual função desenho()? De qual classe?
Pearson Education Slide 8
Exemplo Figuras : Nova Figura Considere um novo tipo de figura:
Classe Triânguloderivada da classe Figura
Função centro() herdada de Figura Funcionará para Triângulos? Ela usa desenho(), a qual é diferente para cada figura! Usará Figura::desenho() Não funciona para triângulos!
Queremos que a função herdada centro () utilize a função Triângulo::desenho() NÃO a função Figura::desenho()
Mas a classe triângulo nem mesmo estava ESCRITAquando Figura::centro() estava! Não se conhece Triângulo’!
Pearson Education Slide 9
Exemplo Figuras : Virtual! Função virtual é a resposta Diz ao compilador:
“Não sei como a função será implementada” “Espere até que ela seja utilizada em um programa” “Então obtenha a implementação da
instãncia
do objeto Chamada de ligação tardia ou ligação
dinâmica Funções virtuais implementam a ligação tardia
Pearson Education Slide 10
Funções virtuais: Outro Exemplo Um exemplo maior é melhor para demonstrar Programa de arquivo de registros para
umaloja de peças de automóveis
Controle das vendas Não conhecemos todas as vendas ainda 1o somente vendas regulares ao varejo Mais tarde: descontos, maior e menor venda,
etc. Dependem de outros fatores além do preço e
dos impostos
Pearson Education Slide 11
Funções Virtuais : Auto-peças O programa precisa:
Calcular as vendas brutas diárias Calcular a maior/menor venda do dia Talvez a média de vendas para o dia
Tudo vem de faturas individuais Mas muitas funções para calcular faturas serão
acrescentadas ‘mais tarde’! Quando diferentes tipos de vendas forem acrescentadas!
Então a função para ‘cálculo da fatura’ será
virtual
Pearson Education Slide 12
Definição da Classe Venda class Sale
{public:
Sale();Sale(double thePrice);double getPrice() const;virtual double bill() const;double savings(const Sale& other) const;
private:double price;
};
Pearson Education Slide 13
Função-Membro economia(savings) e o operador <
double Sale::savings(const Sale& other) const{
return (bill() – other.bill());}
bool operator < ( const Sale& first,const Sale& second)
{return (first.bill() < second.bill());
} Observe que ambos usam a função-membro
fatura(bill)!
Pearson Education Slide 14
Classe Venda Representa as vendas de itens simples sem
nenhum desconto acrescentado ou modificado. Observe a palavra reservada ‘virtual’ na
na declaração da função-membro fatura Impacto: mais tarde, classes derivadas de Venda
podem definir suas próprias versões da função fatura Outras funções-membros de Venda usarão
a versão baseada nos objetos da classe derivada! Elas não usarão automaticamente a versão
de Venda!
Pearson Education Slide 15
Definição da Classe Derivada VendaComDesconto
class DiscountSale : public Sale{public:
DiscountSale();DiscountSale( double thePrice,
double the Discount);double getDiscount() const;void setDiscount(double newDiscount);double bill() const;
private:double discount;
};
Pearson Education Slide 16
Implementação de VendaComDesconto de Fatura()
double DiscountSale::bill() const{
double fraction = discount/100;return (1 – fraction)*getPrice();
} Qualificador ‘virtual’ não se repete na
definição da função ‘Automaticamente’ virtual na classe derivada Declaração (na interface) não requer a
palavra-chave ‘virtual’ (mas usa-se com freqüência)
Pearson Education Slide 17
Implementação de VendaComDesconto de Fatura()
Função virtual na classe-base: ‘Automaticamente’ virtual na classe derivada Declaração da classe derivada (na interface)
Não requer a palavra-chave ‘virtual’ Mas é adicionada com freqüência
por motivos de legibilidade
Pearson Education Slide 18
Classe Derivada VendaComDesconto
A função-membro fatura() de VendaComDescontoé implementada diferentemente do que em Venda
Específica para ‘descontos’
Funções-membros economia e ‘<‘ Usará essa definição de fatura() para todos os
objetos da classe VendaComDesconto! Em vez da versão ‘padrão’ definida na classe
Venda!
Pearson Education Slide 19
Virtual: UAU! Lembre-se da classe Venda escrita muito tempo antes
da classe derivada VendaComDesconto Os membros economia e ‘<‘ compilados antes, sequer
tinham idéia de uma classe VendaComDesconto Mesmo em uma chamada como:
VendaComDesconto d1, d2;d1.economia(d2);
A chamada em economia() para a função fatura()sabe como usar a definição de fatura() dada paraa classe VendaComDesconto
Poderoso!
Pearson Education Slide 20
Virtual: Como? Para escrever programas em C++:
Assuma que isso aconteça por ‘mágica’! Mas a explicação envove a Ligação Tardia
Funções virtuais implementam ligação tardia Diz ao compilador para ‘esperar’ até que a
função seja usada no programa Decide qual definição usar baseado no objeto
que chamou Princípio muito importante de OOP!
Pearson Education Slide 21
Sobrescrita (Overriding) Definição de função virtual modificada
emuma classe derivada
Dizemos que ela foi ‘sobrescrita’ Parecido com redefinição
Lembre-se: Funções-padrão Assim:
Funções virtuais modificadas: sobrescritas Funções não-virtuais modificadas :
redefinidas
Pearson Education Slide 22
Funções Virtuais : Porque não todas? Nós vimos vantagens claras para usarmos
funções virtuais A maior desvantagem: elevado gasto de memória!
Exige mais espaço de armazenamento Ligação tardia ocorre ‘on the fly’ (enquanto o programa roda) então o programa roda mais
lentamente Se não é necessário o uso de funções virtuais,
não devem ser usadas
Pearson Education Slide 23
Funções Virtuais Puras A classe-base pode não ter definições
‘significativas’ para alguns de seus membros! Lembre-se da Classe Figura
Todas as figuras são objetos de classes derivadas
Retângulo, círculos, triângulos, etc. A Classe Figura não tem idéia de como
desenhar! Torne-a uma Função virtual pura:
virtual void desenho() = 0;
Pearson Education Slide 24
Classes-Base Abstratas Funções virtuais não requerem definição
Força todas as classes derivadas a definir‘sua própria’ versão
Classe com uma ou mais funções virtuais purasé chamada de: classe-base abstrata
Pode somente ser usada como classe-base Nenhum objeto pode ser criado a partir dela
Uma vez que ela não tem definições completasde todos os seus membros!
Pearson Education Slide 25
Compatibilidade de Tipo Estendida Dado:
Derivada é uma classe derivada de Base Objetos de tipo Derivada podem ser
atribuídos
a Objetos de tipo Base Mas o contrário NÃO é verdade!
Considere o exemplo anterior: Uma VendaComDesconto “é uma” Venda,
mas
o oposto não é verdade
Pearson Education Slide 26
Exemplo de Compatibilidade de Tipo Estendida
class Animal{public:
string nome;virtual void imprime() const;
};class Cachorro : public Animal{public:
string raca;virtual void imprime() const;
};
Pearson Education Slide 27
Classes Animal e Cachorro Agora dadas as Declarações:
Cachorro vCachorro;Animal vAnimal;
Observe que as variáveis-membros nome eraca são públicas!
Somente com propósito de exemplo!
Pearson Education Slide 28
Usando as Classes Animal e Cachorro Tudo que “é um” Cachorro “é um” Animal:
vcachorro.nome = “Rex”;vcachorro.raca = “Dinamarquês”;vanimal = vcachorro;
Isto é permitido Pode-se atribuir valores a um tipo pai,
mas
não o inverso Um animal “não é um” cachorro
(não necessariamente)
Pearson Education Slide 29
Problema do Fatiamento (Slicing) O valor atribuído à vanimal ‘perde’ seu
campo raca! cout << vanimal.raca;
Produz uma mensagem de ERRO! Chamado de Problema do Fatiamento
Pode parecer apropriado Cachorro foi movido para a variável Animal,
assim deverá ser tratado com um animal Então não tem propriedades de ‘cachorro’
Assunto para um debate filosófico interessante
Pearson Education Slide 30
Resolvendo o Problema do Fatiamento Em C++, o Problema do fatiamento é um
incômodo Ele ainda ‘é um’ Dinamarquês chamado Rex Gostaríamos de nos referir à sua raça, ainda
que o
tratássemos como um Animal Utilizamos ponteiros para variáveis dinâmicas
Pearson Education Slide 31
Exemplo do Problema do Fatiamento Animal *panimal;
Cachorro *pcachorro;pcachorro = new Cachorro;pcachorro->nome = “Rex”;pcachorro->raca = “Dinamarquês”;panimal = pcachorro;
Não podemos acessar o campo raca do objeto apontado por panimal:cout << panimal->raca;// ILEGAL!
Pearson Education Slide 32
Exemplo do Problema do Fatiamento Deve-se usar uma função-membro
virtual:panimal->imprime();
Chama a função-membro imprime na classe
Cachorro Porque ela é virtual
C++ ‘espera’ para ver qual objeto o ponteiro
panimal está atualmente apontando antes de
‘conectar’ a chamada
Pearson Education Slide 33
Destrutores Virtuais Lembre-se: destrutores precisam desalocar
dados dinamicamente alocados Considere:
Base *pBase = new Derivada;…delete pBase;
Chamaria o destrutor da classe-base mesmo queapontasse para o objeto da classe derivada!
Tornar o destrutor virtual resolve isso! Boa política para todos os destrutores serem virtuais
Pearson Education Slide 34
Casting Considere:
Animal vanimal;Cachorro vcachorro;…vcachorro = static_cast<Cachorro>(vanimal); //ILEGAL!
Não se pode converter um animal em um cachorro, mas:vanimal = vcachorro; // Legal!vanimal = static_cast<Animal>(vcachorro); // Também é legal!
Upcasting é seguro Do tipo descendente para um tipo ancestral
Pearson Education Slide 35
Downcasting Downcasting é Perigoso!
Casting de um tipo ancestral para um tipo descendente
Assume que estamos acrescentando informações Pode ser feito com o dynamic_cast:
Animal *panimal;panimal = new Cachorro;Cachorro *pcachorro = dynamic_cast<Cachorro*>(panimal);
Legal, mas perigoso! Downcasting é raramente feito devido às armadilhas
Deve-se controlar todas as informações que serão acrescrentadas
Todas as funções-membros devem ser virtuais
Pearson Education Slide 36
Trabalho Secreto das Funções Virtuais Não é preciso saber como são implementadas
Princípio da ocultação de informação Tabela de funções virtuais
O compilador as cria Tem ponteiros para cada função-membro virtual Aponta para o local correto do código da função
Objetos de classes semelhantes também
têm ponteiros Apontando para a tabela de funções virtuais
Pearson Education Slide 37
Sumário 1 A ligação tardia atrasa a decisão de qual
função-membro será chamada até a execução
Em C++, funções virtuais usam a ligação tardia
Funções virtuais puras não têm definição Classe com pelo menos uma é abstrata Nenhum objeto pode ser criado a partir de
classes abstratas Usadas estritamente como base para outras
classes derivadas
Pearson Education Slide 38
Sumário 2 Objetos de classes derivadas podem ser
atribuídos a objetos de classes-base Membros das classes-base são perdidos:
Problema do fatiamento Atribuições de ponteiros e objetos
dinãmicos Permitem resolver o problema do fatiamento
Torne todos os destrutores virtuais Boa prática de programação Garante a correta desalocação da memória