Kursinnhold
C++ OOP
C++ OOP
Diamantarv
Multippel arv kan føre til en situasjon kjent som diamantproblemet eller diamantarv, som er en betydelig utfordring i objektorienterte programmeringsspråk som støtter multippel arv.
Dette oppstår når en subklasse arver fra to eller flere classes
, som selv arver fra en felles superklasse. Begrepet diamant brukes fordi arvestrukturen ligner formen til en diamant.
main.cpp
class Base {}; class Derived1 : public Base {}; class Derived2 : public Base {}; class Diamond : public Derived1, public Derived2 {};
Hovedproblemet med diamantarv er tvetydigheten det skaper. Siden Diamond
arver fra både Derived1
og Derived2
, som igjen arver fra Base
, finnes det to kopier av Base
i et objekt av Diamond
. Dette kan føre til 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
Nøkkelordet virtual
bidrar til å unngå dette problemet. Du kan løse denne uklarheten gjennom virtuell arv ved å bruke nøkkelordet virtual
. Når Diamond
arver virtuelt, sørger C++ for at kun én kopi av superklassen er til stede, selv om den arves flere ganger gjennom ulike stier.
main.cpp
class Base {}; class Derived1 : virtual public Base {}; class Derived2 : virtual public Base {}; class Diamond : public Derived1, public Derived2 {};
Prøv å løse tvetydighetsproblemet i det forrige eksempelet ved å benytte virtuell arv.
Implementering av diamantarv
For å implementere diamantarv effektivt, bruk virtual-nøkkelordet i superklassen i de mellomliggende classes
. Sørg for konsistent bruk av virtuell arv i alle veier i arvshierarkiet, og vær oppmerksom på rekkefølgen for kall av konstruktører og destruktører.
Løsning av tvetydigheter
En av utfordringene med multippel arv er også å håndtere potensielle tvetydigheter når det gjelder medlemmer med samme navn.
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? }
Hvis begge superklassene har medlemmer med samme navn, kan subklassen være usikker på hvilken som skal brukes. For å løse slike tvetydigheter, kan du bruke scope resolution operatoren (::
) for å spesifisere hvilket medlem fra hvilken baseklasse du ønsker å få tilgang til. For eksempel:
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(); }
Takk for tilbakemeldingene dine!