Contenu du cours
Programmation Orientée Objet en C++
Programmation Orientée Objet en C++
Héritage en Diamant
L'héritage multiple peut conduire à une situation connue sous le nom de problème du diamant ou héritage en diamant, qui constitue un défi majeur dans les langages de programmation orientés objet prenant en charge l'héritage multiple.
Cela se produit lorsqu'une sous-classe hérite de deux ou plusieurs classes
, qui elles-mêmes héritent d'une superclasse commune. Le terme diamant est utilisé car le schéma d'héritage ressemble à la forme d'un diamant.
main.cpp
class Base {}; class Derived1 : public Base {}; class Derived2 : public Base {}; class Diamond : public Derived1, public Derived2 {};
Le principal problème de l'héritage en diamant est l'ambiguïté qu'il engendre. Puisque Diamond
hérite à la fois de Derived1
et de Derived2
, qui héritent eux-mêmes de Base
, il existe deux copies de Base
dans un objet de type Diamond
. Cela peut entraîner une ambiguïté.
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? }
Solution au problème
Le mot-clé virtual
permet d'éviter ce problème. Vous pouvez résoudre cette ambiguïté grâce à l'héritage virtuel en utilisant le mot-clé virtual
. Lorsque Diamond
hérite virtuellement, C++ garantit qu'une seule copie de la superclasse est présente, même si elle est héritée plusieurs fois via différents chemins.
main.cpp
class Base {}; class Derived1 : virtual public Base {}; class Derived2 : virtual public Base {}; class Diamond : public Derived1, public Derived2 {};
Essayez de résoudre le problème d'ambiguïté dans l'exemple précédent en utilisant l'héritage virtuel.
Implémentation de l'héritage en diamant
Pour implémenter efficacement l'héritage en diamant, utiliser le mot-clé virtual dans la déclaration de la superclasse au sein des classes
intermédiaires. Assurer une utilisation cohérente de l'héritage virtuel dans tous les chemins de la hiérarchie d'héritage, et prêter attention à l'ordre d'appel des constructeurs et destructeurs.
Résolution des ambiguïtés
L'un des défis de l'héritage multiple consiste également à gérer les ambiguïtés potentielles concernant les membres portant les mêmes noms.
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 les deux superclasses possèdent des membres portant le même nom, la sous-classe peut ne pas savoir lequel utiliser. Pour résoudre de telles ambiguïtés, il est possible d'utiliser l'opérateur de résolution de portée (::
) afin de spécifier le membre de la classe de base que vous souhaitez accéder. Par exemple :
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(); }
Merci pour vos commentaires !