Ahora sólo sería necesario que las clases Profesor e Investigador heredasen de Persona:
class Persona {
private:
string nombre;
public:
const string &getNombre() const
{ return nombre; }
};
class Profesor : public Persona {
// más cosas ...
Profesor(const string &n, const string &m) : Persona( n )
{ materia = m; }
};
class Investigador : public Persona {
// más cosas ...
public:
Investigador(const string &n, const string &e) : Persona( n )
{ especialidad = e; }
};
En principio, ahora ya no sería necesario ningún truco para que la llamada a getNombre() de un objeto ProfesorUniversitario funcionara ...
ProfesorUniversitario p( "Baltasar", "Tecnología de Objetos", "Máquinas virtuales" );
cout << p.getNombre() << endl;
Sin embargo, no lo hace. De hecho, proporciona un mensaje de error muy extraño (en GNU g++):
getNombre is ambiguous¿Qué está pasando?
candidates are:
Persona::getNombre
Persona::getNombre
Aunque se buscaba una herencia en diamante, es decir, una jerarquía en la que la clase base es Persona, de la que heredan Profesor e Investigador, y de la que a su vez hereda ProfesorUniversitario (de ahí el nombre de este tipo de herencia (tiene nombre, precisamente debido a este problema)), lo que se ha obtenido en cambio, es que Profesor e Investigador tienen cada uno su propia copia propia de la clase Persona como clase base, lo cual explica el mensaje de error obtenido. La razón de esto no es otra que una cuestión de diseño del lenguaje C++.
Se puede "arreglar" este problema de la siguiente forma:
class Profesor : public virtual Persona {Como se puede apreciar, la solución es bastante poco elegante y engorrosa. Hay que poner virtual delante de la herencia de Persona en las clases Profesor e Investigador. Además, la clase ProfesorUniversitario debe también inicializar la clase Persona, pues de otra forma el lenguaje no se ve capaz de optar por una rama (herencia por profesor o investigador) para llegar hasta Persona e inicializarla.
// más cosas ...
Profesor(const string &n, const string &m) : Persona( n )
{ materia = m; }
};
class Investigador : public virtual Persona {
// más cosas ...
public:
Investigador(const string &n, const string &e) : Persona( n )
{ especialidad = e; }
};
class ProfesorUniversitario : public Persona, public Investigador {
public:
ProfesorUniversitario(const string &n, const string &m, const string &e)
: Persona( n ), Investigador( n, e ), Profesor( n, m )
{}
};
Llegados hasta este punto, se torna claro que la herencia múltiple puede parecer beneficiosa en un primer término, pero produce muchos más problemas de los que soluciona en un principio. Por ello se desaconseja su uso, y lenguajes modernos como Java y C# ya no la soportan.