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 keskeinen ongelma on siitä aiheutuva 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? }
Ratkaisu ongelmaan
Avainsana virtual auttaa välttämään tämän ongelman. Tämän epäselvyyden voi ratkaista 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 johdonmukainen virtuaalisen perinnän käyttö kaikissa perintähierarkian 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ällaisen epäselvyyden ratkaisemiseksi voidaan käyttää alueen tarkennusoperaattoria (::) määrittämää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 keskeinen ongelma on siitä aiheutuva 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? }
Ratkaisu ongelmaan
Avainsana virtual auttaa välttämään tämän ongelman. Tämän epäselvyyden voi ratkaista 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 johdonmukainen virtuaalisen perinnän käyttö kaikissa perintähierarkian 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ällaisen epäselvyyden ratkaisemiseksi voidaan käyttää alueen tarkennusoperaattoria (::) määrittämää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!