Timanttiperiytyminen
Moniperintä voi johtaa tilanteeseen, jota kutsutaan nimellä timanttiongelma tai timanttiperintä, mikä on merkittävä haaste olio-ohjelmointikielissä, jotka tukevat moniperintää.
Tämä tapahtuu, kun aliluokka perii kahdesta tai useammasta classes
, jotka itse perivät yhteisestä yliluokasta. Termi timantti viittaa siihen, että perintärakenne muistuttaa timantin muotoa.
main.cpp
1234567class Base {}; class Derived1 : public Base {}; class Derived2 : public Base {}; class Diamond : public Derived1, public Derived2 {};
Timanttiperinnän ensisijainen ongelma on sen aiheuttama epäselvyys. Koska Diamond
perii sekä Derived1
:stä että Derived2
:sta, jotka puolestaan perivät Base
:sta, Base
-oliossa on kaksi kopiota Diamond
:sta. Tämä voi johtaa epäselvyyteen.
main.cpp
12345678910111213141516#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? }
Ongelman ratkaisu
Avainsana virtual
auttaa välttämään tämän ongelman. Voit ratkaista tämän epäselvyyden virtuaalisen perinnän avulla käyttämällä virtual
-avainsanaa. Kun Diamond
perii virtuaalisesti, C++ varmistaa, että yliluokasta on vain yksi kopio, vaikka se periytyisi useamman polun kautta.
main.cpp
1234567class Base {}; class Derived1 : virtual public Base {}; class Derived2 : virtual public Base {}; class Diamond : public Derived1, public Derived2 {};
Yritä ratkaista edellisen esimerkin epäselvyysongelma hyödyntämällä virtuaalista perintää.
Timanttiperinnän toteuttaminen
Timanttiperinnän tehokkaaseen toteuttamiseen käytä virtual-avainsanaa yliluokan määrittelyssä välikurssien classes
. Varmista virtuaalisen perinnän johdonmukainen käyttö kaikissa perintäpoluissa ja huomioi rakentajien ja tuhoajien kutsujärjestys.
Epäselvyyksien ratkaiseminen
Yksi moniperinnän haasteista on myös mahdollisten epäselvyyksien käsittely, kun kyseessä ovat samannimiset jäsenet.
main.cpp
12345678910111213141516171819#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? }
Jos molemmilla yläluokilla on samannimisiä jäseniä, alaluokka ei välttämättä tiedä, kumpaa käyttää. Tällaiset epäselvyydet voidaan ratkaista käyttämällä alueen tarkennusoperaattoria (::
), jolla määritetään, minkä kantaluokan jäsentä halutaan käyttää. Esimerkiksi:
main.cpp
1234567891011121314151617181920#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(); }
Kiitos palautteestasi!
Kysy tekoälyä
Kysy tekoälyä
Kysy mitä tahansa tai kokeile jotakin ehdotetuista kysymyksistä aloittaaksesi keskustelumme