Kursinnehåll
C++ OOP
C++ OOP
Diamantärvning
Multipelt arv kan leda till en situation som kallas diamantproblemet eller diamantarv, vilket är en betydande utmaning i objektorienterade programmeringsspråk som stöder multipelt arv.
Detta uppstår när en subklass ärver från två eller flera classes
, som själva ärver från en gemensam superklass. Termen diamant används eftersom arvstrukturen liknar formen av en diamant.
main.cpp
class Base {}; class Derived1 : public Base {}; class Derived2 : public Base {}; class Diamond : public Derived1, public Derived2 {};
Det huvudsakliga problemet med diamantarv är den tvetydighet som uppstår. Eftersom Diamond
ärver från både Derived1
och Derived2
, vilka i sin tur ärver från Base
, finns det två kopior av Base
inom ett objekt av typen Diamond
. Detta kan leda till tvetydighet.
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ösning på problemet
Nyckelordet virtual
hjälper till att undvika detta problem. Du kan lösa denna tvetydighet genom virtuell arv genom att använda nyckelordet virtual
. När Diamond
ärver virtuellt säkerställer C++ att endast en kopia av superklassen finns, även om den ärvs flera gånger genom olika vägar.
main.cpp
class Base {}; class Derived1 : virtual public Base {}; class Derived2 : virtual public Base {}; class Diamond : public Derived1, public Derived2 {};
Försök att lösa tvetydighetsproblemet i det föregående exemplet genom att använda virtuell arv.
Implementering av diamantarv
För att implementera diamantarv effektivt, använd virtual-nyckelordet i superklassens deklaration inom de intermediära classes
. Säkerställ konsekvent användning av virtuellt arv i alla vägar i arvshierarkin och var uppmärksam på ordningen för anrop av konstruktorer och destruktorer.
Lösning av tvetydigheter
En av utmaningarna med multipelt arv är även att hantera potentiella tvetydigheter när det gäller medlemmar med samma namn.
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? }
Om båda superklasserna har medlemmar med samma namn kan subklassen vara osäker på vilken som ska användas. För att lösa sådana tvetydigheter kan du använda scope resolution operatorn (::
) för att specificera vilken basklassmedlem du vill komma åt. Till exempel:
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(); }
Tack för dina kommentarer!