C++
Home

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