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
Awesome!
Completion rate improved to 3.13
Timanttiperiytyminen
Pyyhkäise näyttääksesi valikon
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!