Contenu du cours
C++ Oop
C++ Oop
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 est un défi important dans les langages de programmation orientés objet qui prennent 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é parce que le schéma d'héritage ressemble à la forme d'un diamant.
main
class Base {}; class Derived1 : public Base {}; class Derived2 : public Base {}; class Diamond : public Derived1, public Derived2 {};
Le principal problème avec l'héritage en diamant est l'ambiguïté qu'il crée. Puisque Diamond hérite à la fois de Derived1 et de Derived2, qui à leur tour héritent de Base, il y a deux copies de Base dans un objet de Diamond. Cela peut entraîner une ambiguïté. Par exemple :
main
#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 aide à éviter ce problème. Vous pouvez résoudre cette ambiguïté par l'héritage virtuel, en utilisant le mot-clé virtual. Lorsqu'un Diamant est hérité virtuellement, C++ garantit qu'une seule copie de la superclasse est présente, même si elle est héritée plusieurs fois par différents chemins.
main
class Base {}; class Derived1 : virtual public Base {}; class Derived2 : virtual public Base {}; class Diamond : public Derived1, public Derived2 {};
Remarque
Essayez de résoudre le problème d'ambiguïté dans l'exemple précédent en utilisant l'héritage virtuel.
Mise en œuvre de l'héritage en diamant
Pour mettre en œuvre efficacement l'héritage en diamant :
- utilisez le mot-clé virtual dans la déclaration de la superclasse dans les classes intermédiaires ;
- assurez-vous de l'utilisation cohérente de l'héritage virtuel dans tous les chemins de la hiérarchie d'héritage ;
- soyez attentif à l'ordre des appels des constructeurs et destructeurs.
Résolution des ambiguïtés
L'un des défis de l'héritage multiple est également de gérer les ambiguïtés potentielles lorsqu'il s'agit de membres portant les mêmes noms.
main
#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 ont des membres portant le même nom, la sous-classe peut ne pas savoir lequel utiliser. Pour résoudre de telles ambiguïtés, vous pouvez utiliser l'opérateur de résolution de portée (::
) pour spécifier le membre de la classe de base que vous souhaitez accéder. Par exemple :
main
#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 !