Moninkertainen perintö C ++: ssa on tehokas, mutta hankala työkalu, joka johtaa usein ongelmiin, jos sitä ei käytetä huolellisesti - ongelmia, kuten Timantti -ongelma.

Tässä artikkelissa keskustelemme timanttiongelmasta, siitä, miten se johtuu useasta perinnöstä ja mitä voit tehdä ongelman ratkaisemiseksi.

Useita perintöjä C ++: ssa

Moninkertainen perintö on a objektiorientoidun ohjelmoinnin (OOP) ominaisuus jossa alaluokka voi periä useammasta kuin yhdestä superluokasta. Toisin sanoen lapsiluokalla voi olla useampi kuin yksi vanhempi.

Alla oleva kuva esittää kuvallisen esityksen useista perinnöistä.

Yllä olevassa kaaviossa luokka C on luokka A ja luokka B sen vanhempina.

Jos tarkastelemme tosielämän skenaariota, lapsi perii isältään ja äidiltään. Joten lasta voidaan edustaa johdetulla luokalla, jonka vanhemmat ovat "Isä" ja "Äiti". Samoin meillä voi olla monia tällaisia ​​tosielämän esimerkkejä moninkertaisesta perinnöstä.

Moninkertaisessa perinnössä perityn luokan konstruktorit suoritetaan siinä järjestyksessä kuin ne peritään. Toisaalta tuhoajat suoritetaan perintönsä päinvastaisessa järjestyksessä.

instagram viewer

Tarkastellaan nyt moninkertaista perintöä ja tarkistetaan esineiden rakentamisen ja tuhoamisen järjestys.

Koodikuva useasta perinnöstä

Usean perinnön havainnollistamiseksi olemme ohjelmoineet tarkasti yllä olevan esityksen C ++: ssa. Ohjelman koodi on alla.

#sisältää
käyttämällä nimiavaruutta std;
luokka A // perusluokka A, jossa on rakentaja ja tuhoaja
{
julkinen:
A () {cout << "luokka A:: Rakentaja" << endl; }
~ A () {cout << "luokka A:: Tuhoaja" << endl; }
};
luokka B // perusluokka B, jossa on rakentaja ja tuhoaja
{
julkinen:
B () {cout << "class B:: Constructor" << endl; }
~ B () {cout << "luokka B:: Tuhoaja" << endl; }
};
luokka C: julkinen B, julkinen A // johdettu luokka C perii luokan A ja sitten luokan B (huomioi järjestys)
{
julkinen:
C () {cout << "luokka C:: Rakentaja" << endl; }
~ C () {cout << "luokka C:: Tuhoaja" << endl; }
};
int main () {
Cc;
palauta 0;
}

Yllä olevasta ohjelmasta saatu tulos on seuraava:

luokka B:: Rakentaja
luokka A:: Rakentaja
luokka C:: Rakentaja
luokka C:: Destructor
luokka A:: Tuhoaja
luokka B:: Destructor

Jos tarkastelemme lähtöä, näemme, että konstruktorit kutsutaan järjestyksessä B, A ja C, kun tuhoajat ovat päinvastaisessa järjestyksessä. Nyt kun tiedämme moninkertaisen perinnön perusteet, siirrymme keskustelemaan timanttiongelmasta.

Timantti -ongelma, selitetty

Timantti -ongelma ilmenee, kun lapsiluokka perii kahdelta vanhempi luokalta, joilla molemmilla on yhteinen isovanhempi -luokka. Tämä näkyy alla olevassa kaaviossa:

Tässä meillä on luokka Lapsi perii luokilta Isä ja Äiti. Nämä kaksi luokkaa puolestaan ​​perivät luokan Henkilö koska sekä isä että äiti ovat persoona.

Kuten kuvassa näkyy, luokkalapsi perii luokan Henkilön piirteet kahdesti - kerran Isältä ja uudelleen äidiltä. Tämä aiheuttaa epäselvyyttä, koska kääntäjä ei ymmärrä, mihin suuntaan mennä.

Tästä skenaariosta syntyy timantin muotoinen perintökaavio, ja sitä kutsutaan tunnetusti nimellä "Timanttiongelma".

Koodikuva timanttiongelmasta

Alla olemme edustaneet yllä olevaa esimerkkiä timanttimaisesta perinnöstä ohjelmallisesti. Koodi on alla:

#sisältää
käyttämällä nimiavaruutta std;
luokan henkilö {// luokan henkilö
julkinen:
Henkilö (int x) {cout << "Person:: Person (int) nimeltä" << endl; }
};
luokan isä: julkinen henkilö {// luokan isä perii persoonan
julkinen:
Isä (int x): Henkilö (x) {
cout << "Isä:: Isä (int) nimeltään" << endl;
}
};
luokka Äiti: julkinen henkilö {// luokkaäiti perii persoonan
julkinen:
Äiti (int x): henkilö (x) {
cout << "Äiti:: Äiti (int) nimeltään" << endl;
}
};
luokka Lapsi: julkinen isä, julkinen äiti {// Lapsi perii isän ja äidin
julkinen:
Lapsi (int x): äiti (x), isä (x) {
cout << "Lapsi:: Lapsi (int) nimeltään" << endl;
}
};
int main () {
Lapsi lapsi (30);
}

Seuraavassa on tämän ohjelman tulos:

Henkilö:: Henkilö (int) kutsutaan
Isä:: Isä (int) soitti
Henkilö:: Henkilö (int) kutsutaan
Äiti:: Äiti (int) soitti
Lapsi:: Lapsi (int) kutsutaan

Nyt näet epäselvyyden täältä. Henkilöluokan konstruktori kutsutaan kahdesti: kerran, kun Isä -luokan objekti luodaan, ja seuraavaksi, kun Äiti -luokan objekti luodaan. Henkilöluokan ominaisuudet periytyvät kahdesti, mikä aiheuttaa epäselvyyttä.

Koska Person -luokan konstruktori kutsutaan kahdesti, tuhoajaa kutsutaan myös kahdesti, kun Child -luokan objekti tuhotaan.

Jos olet nyt ymmärtänyt ongelman oikein, keskustele Diamond -ongelman ratkaisusta.

Timantti -ongelman korjaaminen C ++: ssa

Ratkaisu timanttiongelmaan on käyttää virtuaalinen avainsana. Teemme kahdesta vanhempainluokasta (jotka perivät samalta isovanhempi -luokalta) virtuaaliluokat, jotta vältetään kaksi isovanhempien luokan kopiota lapsiluokassa.

Muutetaan yllä oleva kuva ja tarkistetaan tulos:

Koodikuva timanttiongelman korjaamiseksi

#sisältää
käyttämällä nimiavaruutta std;
luokan henkilö {// luokan henkilö
julkinen:
Henkilö () {cout << "Person:: Person () nimeltä" << endl; } // Perusrakentaja
Henkilö (int x) {cout << "Person:: Person (int) nimeltä" << endl; }
};
luokan isä: virtuaalinen julkinen henkilö {// luokan isä perii persoonan
julkinen:
Isä (int x): Henkilö (x) {
cout << "Isä:: Isä (int) nimeltään" << endl;
}
};
luokka Äiti: virtuaalinen julkinen henkilö {// luokkaäiti perii persoonan
julkinen:
Äiti (int x): henkilö (x) {
cout << "Äiti:: Äiti (int) nimeltään" << endl;
}
};
luokan lapsi: julkinen isä, julkinen äiti {// luokkalaps perii isän ja äidin
julkinen:
Lapsi (int x): äiti (x), isä (x) {
cout << "Lapsi:: Lapsi (int) nimeltään" << endl;
}
};
int main () {
Lapsi lapsi (30);
}

Tässä olemme käyttäneet virtuaalinen avainsana, kun luokat Isä ja Äiti perivät Henkilö -luokan. Tätä kutsutaan yleensä "virtuaaliseksi perinnöksi", joka takaa, että vain yksi perityn luokan esiintymä (tässä tapauksessa henkilöluokka) välitetään.

Toisin sanoen lapsi -luokalla on yksi persoona -luokka, jonka jakavat sekä isä- että äiti -luokat. Kun henkilöluokassa on yksi esiintymä, epäselvyys ratkaistaan.

Yllä olevan koodin lähtö on annettu alla:

Henkilö:: Henkilö () soitettu
Isä:: Isä (int) soitti
Äiti:: Äiti (int) soitti
Lapsi:: Lapsi (int) kutsutaan

Täältä näet, että luokka Person konstruktori kutsutaan vain kerran.

Yksi asia, joka on huomattava virtuaalisesta perinnöstä, on se, että vaikka parametrin rakentaja Isä ja äiti -luokan rakentajat kutsuvat nimenomaan henkilöluokkaa alustuksen kautta luettelot, vain henkilöluokan perusrakentajaa kutsutaan.

Tämä johtuu siitä, että on olemassa vain yksi virtuaalisen perusluokan esiintymä, jonka jakavat useat luokat, jotka perivät sen.

Estääkseen perusrakentajaa suorittamasta useita kertoja, sen perivä luokka ei kutsu virtuaalisen perusluokan konstruktoria. Sen sijaan betoniluokan rakentaja kutsuu rakentajan.

Yllä olevassa esimerkissä luokka Child kutsuu suoraan luokan Henkilö perusrakentajaa.

Aiheeseen liittyviä: Aloittelijan opas vakiomallikirjastoon C ++: ssa

Entä jos sinun on suoritettava perusluokan parametroitu konstruktori? Voit tehdä niin kutsumalla sitä nimenomaisesti lapsiluokassa Isä- tai Äiti -luokan sijaan.

Timantti -ongelma C ++: ssa, ratkaistu

Timanttiongelma on epäselvyys, joka syntyy moninkertaisessa perinnössä, kun kaksi vanhempainluokkaa perii samasta isovanhempi -luokasta ja molemmat vanhemmat luokat perivät yhden lapsiluokan. Ilman virtuaalista perintöä lapsiluokka perii isovanhemman luokan ominaisuudet kahdesti, mikä johtaa epäselvyyteen.

Tämä voi esiintyä usein reaalimaailman koodissa, joten on tärkeää puuttua tähän epäselvyyteen aina, kun se havaitaan.

Timantti -ongelma korjataan käyttämällä virtuaalista perintöä, jossa virtuaalinen avainsanaa käytetään, kun vanhemmat luokat perivät jaetulta isovanhemman luokalta. Näin tekemällä vain yksi kopio isovanhemman luokasta tehdään, ja isovanhemman luokan objektirakentamisen suorittaa lapsiluokka.

JaaTweetSähköposti
10 parasta aloittelijaprojektia uusille ohjelmoijille

Haluatko oppia ohjelmointia, mutta et tiedä mistä aloittaa? Nämä aloittelijoiden ohjelmointiprojektit ja opetusohjelmat aloittavat sinut.

Lue seuraava

Liittyvät aiheet
  • Ohjelmointi
  • C Ohjelmointi
Kirjailijasta
MUO: n henkilökunta

tilaa uutiskirjeemme

Liity uutiskirjeeseemme saadaksesi teknisiä vinkkejä, arvosteluja, ilmaisia ​​e -kirjoja ja ainutlaatuisia tarjouksia!

Klikkaa tästä tilataksesi