Contenido del Curso
POO en C++
POO en C++
Herencia Diamante
La herencia múltiple puede conducir a una situación conocida como el problema del diamante o herencia en diamante, que representa un desafío importante en los lenguajes de programación orientados a objetos que admiten herencia múltiple.
Esto ocurre cuando una subclase hereda de dos o más classes
, que a su vez heredan de una superclase común. El término diamante se utiliza porque el esquema de herencia se asemeja a la forma de un diamante.
main.cpp
class Base {}; class Derived1 : public Base {}; class Derived2 : public Base {}; class Diamond : public Derived1, public Derived2 {};
El principal problema de la herencia en diamante es la ambigüedad que genera. Dado que Diamond
hereda tanto de Derived1
como de Derived2
, que a su vez heredan de Base
, existen dos copias de Base
dentro de un objeto de Diamond
. Esto puede provocar ambigüedad.
main.cpp
#include <iostream> class Base { public: void display() { std::cout << "Base display()" << std::endl; } }; class Derived1 : public Base { }; class Derived2 : public Base { }; class Diamond : public Derived1, public Derived2 { }; int main() { Diamond obj; obj.display(); // Ambiguity: Which display() method should be called? }
Solución al problema
La palabra clave virtual
ayuda a evitar este problema. Puede abordar esta ambigüedad mediante la herencia virtual utilizando la palabra clave virtual
. Cuando Diamond
hereda de forma virtual, C++ garantiza que solo haya una copia de la superclase, incluso si se hereda varias veces a través de diferentes rutas.
main.cpp
class Base {}; class Derived1 : virtual public Base {}; class Derived2 : virtual public Base {}; class Diamond : public Derived1, public Derived2 {};
Intenta resolver el problema de ambigüedad en el ejemplo anterior utilizando la herencia virtual.
Implementación de la herencia diamante
Para implementar la herencia diamante de manera efectiva, utiliza la palabra clave virtual en la declaración de la superclase dentro de las classes
intermedias. Asegúrate de un uso consistente de la herencia virtual en todos los caminos de la jerarquía de herencia y presta atención al orden de llamadas de constructores y destructores.
Resolución de ambigüedades
Uno de los desafíos de la herencia múltiple es también tratar con posibles ambigüedades cuando se trata de miembros con los mismos nombres.
main.cpp
#include <iostream> class Base {}; class Derived1 : public Base { public: void display() { std::cout << "Derived1 display()" << std::endl; } }; class Derived2 : public Base { public: void display() { std::cout << "Derived2 display()" << std::endl; } }; class Diamond : public Derived1, public Derived2 { }; int main() { Diamond obj; obj.display(); // Ambiguity: Which display() method should be called? }
Si ambas superclases tienen miembros con el mismo nombre, la subclase puede no saber cuál utilizar. Para resolver tales ambigüedades, se puede utilizar el operador de resolución de ámbito (::
) para especificar a qué miembro de la clase base se desea acceder. Por ejemplo:
main.cpp
#include <iostream> class Base {}; class Derived1 : public Base { public: void display() { std::cout << "Derived1 display()" << std::endl; } }; class Derived2 : public Base { public: void display() { std::cout << "Derived2 display()" << std::endl; } }; class Diamond : public Derived1, public Derived2 { }; int main() { Diamond obj; obj.Derived1::display(); obj.Derived2::display(); }
¡Gracias por tus comentarios!