Kursinhalt
C++ OOP
C++ OOP
Diamantvererbung
Mehrfachvererbung kann zu einer Situation führen, die als Diamond Problem oder Diamantvererbung bekannt ist. Dies stellt eine bedeutende Herausforderung in objektorientierten Programmiersprachen dar, die Mehrfachvererbung unterstützen.
Dies tritt auf, wenn eine Unterklasse von zwei oder mehr classes
erbt, die ihrerseits von einer gemeinsamen Oberklasse erben. Der Begriff Diamant wird verwendet, weil das Vererbungsschema die Form eines Diamanten hat.
main.cpp
class Base {}; class Derived1 : public Base {}; class Derived2 : public Base {}; class Diamond : public Derived1, public Derived2 {};
Das Hauptproblem bei der Diamantvererbung ist die dadurch entstehende Mehrdeutigkeit. Da Diamond
sowohl von Derived1
als auch von Derived2
erbt, die wiederum von Base
erben, existieren zwei Kopien von Base
innerhalb eines Objekts von Diamond
. Dies kann zu Mehrdeutigkeiten führen.
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? }
Lösung des Problems
Das Schlüsselwort virtual
hilft, dieses Problem zu vermeiden. Sie können diese Mehrdeutigkeit durch virtuelle Vererbung mit dem Schlüsselwort virtual
beheben. Wenn Diamond
virtuell erbt, stellt C++ sicher, dass nur eine Kopie der Oberklasse vorhanden ist, selbst wenn sie mehrfach über verschiedene Pfade geerbt wird.
main.cpp
class Base {}; class Derived1 : virtual public Base {}; class Derived2 : virtual public Base {}; class Diamond : public Derived1, public Derived2 {};
Versuchen Sie, das Mehrdeutigkeitsproblem im vorherigen Beispiel durch die Verwendung von virtueller Vererbung zu lösen.
Implementierung der Diamond-Vererbung
Um die Diamond-Vererbung effektiv zu implementieren, verwenden Sie das virtual-Schlüsselwort in der Oberklassen-Deklaration innerhalb der intermediären classes
. Achten Sie auf die konsistente Verwendung der virtuellen Vererbung in allen Pfaden der Vererbungshierarchie und berücksichtigen Sie die Reihenfolge der Aufrufe von Konstruktoren und Destruktoren.
Auflösung von Mehrdeutigkeiten
Eine der Herausforderungen der Mehrfachvererbung ist auch der Umgang mit möglichen Mehrdeutigkeiten bei Mitgliedern mit denselben Namen.
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? }
Wenn beide Oberklassen Mitglieder mit demselben Namen besitzen, weiß die Unterklasse möglicherweise nicht, welches verwendet werden soll. Um solche Mehrdeutigkeiten zu lösen, kann der Gültigkeitsbereichsauflösungsoperator (::
) verwendet werden, um anzugeben, auf welches Mitglied der Basisklasse zugegriffen werden soll. Zum Beispiel:
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(); }
Danke für Ihr Feedback!