Cursusinhoud
C++ OOP
C++ OOP
Diamant-erfenis
Meervoudige overerving kan leiden tot een situatie die bekend staat als het diamond-probleem of diamond-inheritance, wat een aanzienlijke uitdaging vormt in objectgeoriënteerde programmeertalen die meervoudige overerving ondersteunen.
Dit doet zich voor wanneer een subklasse erft van twee of meer classes
, die op hun beurt erven van een gemeenschappelijke superklasse. De term diamond wordt gebruikt omdat het overervingsschema de vorm van een diamant heeft.
main.cpp
class Base {}; class Derived1 : public Base {}; class Derived2 : public Base {}; class Diamond : public Derived1, public Derived2 {};
Het belangrijkste probleem bij diamond-inheritance is de ambiguïteit die het veroorzaakt. Omdat Diamond
erft van zowel Derived1
als Derived2
, die op hun beurt erven van Base
, zijn er twee kopieën van Base
binnen een object van Diamond
. Dit kan leiden tot ambiguïteit.
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? }
Oplossing voor het probleem
Het sleutelwoord virtual
helpt om dit probleem te voorkomen. U kunt deze onduidelijkheid oplossen via virtuele overerving door het sleutelwoord virtual
te gebruiken. Wanneer Diamond
virtueel erft, zorgt C++ ervoor dat er slechts één kopie van de superklasse aanwezig is, zelfs als deze via verschillende paden meerdere keren wordt geërfd.
main.cpp
class Base {}; class Derived1 : virtual public Base {}; class Derived2 : virtual public Base {}; class Diamond : public Derived1, public Derived2 {};
Probeer het ambiguïteitsprobleem in het vorige voorbeeld op te lossen door gebruik te maken van virtuele overerving.
Implementatie van Diamond Inheritance
Voor een effectieve implementatie van diamond inheritance, gebruik het virtual-keyword in de superklasse-declaratie binnen de tussenliggende classes
. Zorg voor consistente toepassing van virtuele overerving in alle paden van de overervingshiërarchie en let op de volgorde van aanroepen van constructors en destructors.
Oplossen van ambiguïteiten
Een van de uitdagingen van meervoudige overerving is het omgaan met mogelijke ambiguïteiten bij leden met dezelfde 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? }
Als beide superklassen leden met dezelfde naam hebben, weet de subklasse mogelijk niet welke gebruikt moet worden. Om dergelijke ambiguïteiten op te lossen, kun je de scope-resolutie-operator (::
) gebruiken om aan te geven van welke basisklasse je het lid wilt benaderen. Bijvoorbeeld:
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(); }
Bedankt voor je feedback!