Programação Orientada a Objetos · 2015-08-24 · 24/08/15 Programação Orientada a Objetos –...
Transcript of Programação Orientada a Objetos · 2015-08-24 · 24/08/15 Programação Orientada a Objetos –...
Programação Orientada a Objetos
Renato Dourado MaiaUniversidade Estadual de Montes Claros
Engenharia de Sistemas
HERANÇA E COMPOSIÇÃO
24/08/15 Programação Orientada a Objetos – Renato Dourado Maia 2/26
Na Última Aula...
• Considere a definição de um tipo como Shape, a ser utilizado em um sistema gráfico. O sistema deve su-portar círculos, triângulos e quadrados:
class Point { /* ... */};class Color{ /* ... */};enum Kind { circle, triangle, square };class Shape {
Kind k; Point center;Color col;
public:void draw( );void rotate(float ang);// ...
};
void Shape :: draw( ){ switch (k) { case circle:
// desenha o circulo break; case triangle:
// desenha o triangulo break; case square:
// desenha o quadrado break; } // end switch}
24/08/15 Programação Orientada a Objetos – Renato Dourado Maia 3/26
Na Última Aula...
• Problemas:– Funções como draw() precisam conhecer todos os tipos
de Shape que possam existir...– A função deve ser modificada toda vez que um novo Sha-
pe for adicionado ao sistema:✔ O código de draw é aumentado a cada inclusão de um Shape di-
ferente.✔ Na realidade, todas as funções que trabalham com shapes
terão que ser examinadas e modificadas!
24/08/15 Programação Orientada a Objetos – Renato Dourado Maia 4/26
Na Última Aula...
• Problemas:– Um novo Shape poderá ser adicionado apenas no caso de
se ter acesso ao código fonte de todas as operações...– A parte de dados de Shape tem que ser escolhida de ma-
neira que acomode todas as possíveis representações de uma forma, seja ela qual for...
24/08/15 Programação Orientada a Objetos – Renato Dourado Maia 5/26
Na Última Aula...
• Pensando na solução:– Uma saída está em se agrupar o que é comum a todas as
Shapes (elas possuem uma forma, uma cor, podem ser de-senhadas, giradas, etc) em uma classe, e as propriedades e métodos específicos de triângulos, círculos e demais shapes em classes derivadas:
✔ Isso já foi visto: herança!
24/08/15 Programação Orientada a Objetos – Renato Dourado Maia 6/26
Na Última Aula...
• Pensando na solução:
Circ le
draw()
Square
draw()
Triangle
draw()()
Shape
draw()
24/08/15 Programação Orientada a Objetos – Renato Dourado Maia 7/26
Na Última Aula...
• Problema da solução:– Seja o código a seguir:
class Shape {// ...public: void draw( ) { cout << “Shape::draw”; }};class Triangle : public Shape {// ...public: void draw( ) { cout << “Triangle::draw”;}};
void teste(Shape & a) { a.draw();}int main() { Triangle t; teste(t); // Vai chamar draw de Shape! E não de Triangle! }
24/08/15 Programação Orientada a Objetos – Renato Dourado Maia 8/26
Na Última Aula...
E agora, quem poderá nos ajudar?
24/08/15 Programação Orientada a Objetos – Renato Dourado Maia 9/26
O Chapolim Colorado?
O POLIMORFISMO É A SOLUÇÃO!
24/08/15 Programação Orientada a Objetos – Renato Dourado Maia 10/26
Polimorfismo – A Solução
• A solução anterior só funciona em C++ se forem in-troduzidas as funções virtuais, que adiam a ligação entre o objeto e a função chamada para o tempo de execução: – Isso permite o Polimorfismo...
24/08/15 Programação Orientada a Objetos – Renato Dourado Maia 11/26
Polimorfismo – A Solução
Shape
<<virtual>> draw()
Circ le
<<virtual>> draw()
Square
<<virtual>> draw()
Triangle
<<virt ual>> draw()()
24/08/15 Programação Orientada a Objetos – Renato Dourado Maia 12/26
Polimorfismo – A Soluçãoclass Shape{ // ... virtual void draw( );};class Triangle : public Shape { // ... virtual void draw( ); // virtual é opcional};
void teste(Shape & a) { a.draw();}int main() { Triangle t; teste(t); // Agora, chama draw de Triangle!}
24/08/15 Programação Orientada a Objetos – Renato Dourado Maia 13/26
Polimorfismo – A Solução
• Sempre que o código original da função virtual na classe base não implementa a lógica que for deseja-da na classe derivada, basta implementar uma nova função, com o mesmo protótipo, na classe derivada.
24/08/15 Programação Orientada a Objetos – Renato Dourado Maia 14/26
Tabela de Funções Virtuais
Como o programa pode fazer a ligação objeto/função em
tempo de execução?
24/08/15 Programação Orientada a Objetos – Renato Dourado Maia 15/26
Tabela de Funções Virtuais
• Exemplo:class ClBase{ public: virtual void f1(int); virtual void f2(); int f3();};class ClDeriv : public ClBase { public: void f2(); int f3(); // Não deveria estar fazendo isso! virtual int f4(float);};
24/08/15 Programação Orientada a Objetos – Renato Dourado Maia 16/26
Tabela de Funções Virtuais
TFV de ClBase
f1
f2
TFV de ClDeriv
f1
f2
f4
void ClBase :: f1(int) { ... }void ClBase :: f2() { ... }
void ClDeriv :: f2(int) { ... }void ClDeriv :: f4(float) { ... }
f3() não é virtual. Ela foi sobrecarregada em ClDeriv, mas não sepode identificar a chamada em tempo de execução, porque ela
não está na tabela de funções virtuais.
24/08/15 Programação Orientada a Objetos – Renato Dourado Maia 17/26
Funções Virtuais
Por que não se escolheu fazer todas as funções virtuais
em C++?
24/08/15 Programação Orientada a Objetos – Renato Dourado Maia 18/26
Funções Virtuais
• Em Java, todas as funções são virtuais. • Por que em C++ as funções não são automaticamen-
te virtuais, sendo necessário especificar aquelas para as quais se quer comportamento polimórfico?
24/08/15 Programação Orientada a Objetos – Renato Dourado Maia 19/26
Funções Virtuais
• Questões associadas à eficiência do código:– Se não forem utilizadas funções virtuais, não haverá o o-verhead associado a elas:
✔ Tabela de funções virtuais, mais um ponteiro para a tabela por ob-jeto.
– Stroustrup:✔ “If you don’t use it, you don’t pay for it.”
– Se todas as funções fossem virtuais, não poderia existir o conceito de funções inline...
24/08/15 Programação Orientada a Objetos – Renato Dourado Maia 20/26
Construtores e Destrutores
• Construtores não podem ser funções virtuais– Quando um objeto que contém funções virtuais é criado,
seu ponteiro para a tabela de funções virtuais precisa ser inicializado corretamente.
✔ Isso deve ser efetuado antes que haja a possibilidade de se cha-mar qualquer função virtual.
• Essa é uma atividade realizada pelo construtor: – O compilador (secretamente) insere código no início do
construtor para realizar essa tarefa.
24/08/15 Programação Orientada a Objetos – Renato Dourado Maia 21/26
Construtores e Destrutores
• Lembre-se de que, quando se constrói um objeto de uma classe derivada, o construtor da classe base também é executado.
• Porém, podem-se chamar funções virtuais dentro dos construtores: – A função que será executada é correspondente à “parcela
do objeto” que está sendo construída naquele momento, ou seja, se a função é chamada dentro do construtor da classe base, a função virtual que será executada será a da classe base!
24/08/15 Programação Orientada a Objetos – Renato Dourado Maia 22/26
Construtores e Destrutores
• Se o polimorfismo vai ser utilizado, os destrutores devem ser virtuais!
class Base { //Código com problema: destrutor de Base não virtual public : ~Base() {cout << "\n\tDestruindo a Parte da Base!";}};class Derivada : public Base { public : ~Derivada() {cout << "\n\tDestruindo a Parte da Derivada!";}};
int main() { Derivada deriv; Base * ptrBase = new Base; cout << "\nDeleta ObjBase : "; delete ptrBase; ptrBase = new Derivada; cout << "\nDeleta ObjDeriv : "; delete ptrBase; return 0; }
Resultado problemático:Deleta ObjBase : Destruindo a Parte da Base!Deleta ObjDeriv : Destruindo a Parte da Base! Destruindo a Parte da Derivada! Destruindo a Parte da Base!
24/08/15 Programação Orientada a Objetos – Renato Dourado Maia 23/26
Construtores e Destrutores
• Se o polimorfismo vai ser utilizado, os destrutores devem ser virtuais:– Se forem alocados objetos da classe derivada a partir de
ponteiros da classe base com destrutores não virtuais, somente o destrutor da Parte Base é chamado, apesar de ptrBase estar apontando, no segundo caso, para um obje-to da classe Derivada.
• Repetindo: o destrutor deve ser virtual para que o comportamento seja como o esperado.
24/08/15 Programação Orientada a Objetos – Renato Dourado Maia 24/26
Construtores e Destrutores
• Se o polimorfismo vai ser utilizado, os destrutores devem ser virtuais!class Base { public : virtual ~Base() {cout << "\n\tDestruindo a Parte da Base!";}};
int main() { Derivada deriv; Base * ptrBase = new Base; cout << "\nDeleta ObjBase : "; delete ptrBase; ptrBase = new Derivada; cout << "\nDeleta ObjDeriv : "; delete ptrBase; return 0; }
Resultado:Deleta ObjBase : Destruindo a Parte da Base!Deleta ObjDeriv : Destruindo a Parte da Derivada! Destruindo a Parte da Base! Destruindo a Parte da Derivada! Destruindo a Parte da Base!
24/08/15 Programação Orientada a Objetos – Renato Dourado Maia 25/26
Importante
• Esta apresentação é uma adaptação do material ori-ginalmente desenvolvido pelo professor Renato Car-doso Mesquita, do Departamento de Engenharia Elé-trica da Universidade Federal de Minas Gerais.
http://www.cpdee.ufmg.br/~renato
24/08/15 Programação Orientada a Objetos – Renato Dourado Maia 26/26
That's All Folks!