•
Herança Multipla e classes base virtual
A classe ios é a classe base tanto de istream como de ostream.
Elas são formadas de herança simples. A classe iostream herda tanto de istream
como de ostream.
Essa herança é chamada de herança losango ( diamond ).
Como as classes ostream e istream herdam de ios, existe um problema potencial
para iostream.
A classe iostream poderia conter objetos da superclasse duplicados.
Em uma conversão de iostream para ios poderia resultar em dois objetos ios, o
que geraria um erro. Por que o compilador não saberia qual usar.
Para resolver este problema usamos classe base virtual.
- Subobjetos duplicados consomem memória!
Exemplo do problema
#include <iostream>
using std::cout;
using std::endl;
class Base {
public:
virtual void print() const = 0; // virtual pura
};
class Derivada1 : public Base {
public:
// sobreescreve print
void print() const { cout << "Derivada 1" << endl;
}
};
class Derivada2 : public Base {
public:
// sobreescreve print
void print() const { cout << "Derivada 2" << endl;
}
};
class Multipla : public Derivada1, public Derivada2 {
public:
// qualifica qual a versão da impressão
void print() const { Derivada2::print(); }
};
int main()
{
Multipla multi;
Derivada1 primeira;
Derivada2 segunda;
Base *array[3];
array[0] = &multi; // erro, ambiguo
array[1] = &primeira;
array[2] = &segunda;
// invoca impressão
polimorfica
for ( int i=0; i<3; i++ )
{
array[ i ]->print();
}
return 0;
}
Ocorre um erro quando o endereço de multi é implicitamente convertido
para base, que torna naturalmente os metodos print ambiguos.
Esse problema é resolvido com a herança virtual. Para isso,
basta colocar que a herança é virtual.
No exemplo, somente uma classe base é herada para a multipla.
#include <iostream>
using std::cout;
using std::endl;
class Base {
public:
virtual void print() const = 0; // virtual pura
};
class Derivada1 : virtual public Base {
public:
// sobreescreve print
void print() const { cout << "Derivada 1" << endl; }
};
class Derivada2 : virtual public Base {
public:
// sobreescreve print
void print() const { cout << "Derivada 2" << endl; }
};
class Multipla : public Derivada1, public Derivada2 {
public:
// qualifica qual a versão da impressão
void print() const { Derivada2::print(); }
};
int main()
{
Multipla multi;
Derivada1 primeira;
Derivada2 segunda;
Base *array[3];
array[0] = &multi; // erro, ambiguo
array[1] = &primeira;
array[2] = &segunda;
// invoca impressão
polimorfica
for ( int i=0; i<3; i++ )
{
array[ i ]->print();
}
return 0;
}
- BOM, e isso é o C++..
Se você acompanhou até aqui, meus parabéns =)
|