Kursinhalt
C++ OOP
C++ OOP
Diamantvererbung
Mehrfachvererbung kann zu einer Situation führen, die als Diamantproblem oder Diamantvererbung bekannt ist, was eine bedeutende Herausforderung in objektorientierten Programmiersprachen darstellt, die Mehrfachvererbung unterstützen.
Dies tritt auf, wenn eine Unterklasse von zwei oder mehr Klassen erbt, die selbst von einer gemeinsamen Oberklasse erben. Der Begriff Diamant wird verwendet, weil das Vererbungsschema die Form eines Diamanten hat.
main
class Base {}; class Derived1 : public Base {}; class Derived2 : public Base {}; class Diamond : public Derived1, public Derived2 {};
Das Hauptproblem bei der Diamantvererbung ist die Mehrdeutigkeit, die sie erzeugt. Da Diamond sowohl von Derived1 als auch von Derived2 erbt, die wiederum von Base erben, gibt es zwei Kopien von Base innerhalb eines Objekts von Diamond. Dies kann zu Mehrdeutigkeit führen. Zum Beispiel:
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? }
Lösung des Problems
Das Schlüsselwort virtual hilft, dieses Problem zu vermeiden. Sie können diese Mehrdeutigkeit durch virtuelle Vererbung ansprechen, indem Sie das Schlüsselwort virtual verwenden. Wenn ein Diamant virtuell geerbt wird, stellt C++ sicher, dass nur eine Kopie der Oberklasse vorhanden ist, selbst wenn sie mehrfach über verschiedene Pfade geerbt wird.
main
class Base {}; class Derived1 : virtual public Base {}; class Derived2 : virtual public Base {}; class Diamond : public Derived1, public Derived2 {};
Hinweis
Versuchen Sie, das Mehrdeutigkeitsproblem im vorherigen Beispiel durch die Nutzung der virtuellen Vererbung zu lösen.
Implementierung der Diamantvererbung
Um die Diamantvererbung effektiv zu implementieren:
- Verwenden Sie das Schlüsselwort virtual in der Oberklasse-Deklaration in den Zwischenklassen;
- Stellen Sie sicher, dass virtuelle Vererbung in allen Pfaden der Vererbungshierarchie konsistent verwendet wird;
- Achten Sie auf die Reihenfolge der Aufrufe von Konstruktoren und Destruktoren.
Auflösung von Mehrdeutigkeiten
Eine der Herausforderungen der Mehrfachvererbung besteht auch darin, mit potenziellen Mehrdeutigkeiten umzugehen, wenn es um Mitglieder mit denselben Namen geht.
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? }
Wenn beide Superklassen Mitglieder mit demselben Namen haben, weiß die Unterklasse möglicherweise nicht, welches sie verwenden soll. Um solche Mehrdeutigkeiten zu lösen, können Sie den Bereichsauflösungsoperator (::
) verwenden, um anzugeben, auf welches Mitglied der Basisklasse Sie zugreifen möchten. Zum Beispiel:
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(); }
Danke für Ihr Feedback!