Več podedovanja v C ++ je močno, a zapleteno orodje, ki pogosto povzroči težave, če jih ne uporabljate previdno - težave, kot je problem diamanta.

V tem članku bomo razpravljali o diamantnem problemu, kako izhaja iz večkratnega dedovanja in kaj lahko storite, da ga rešite.

Več dediščin v C ++

Večkratna dediščina je a značilnost objektno usmerjenega programiranja (OOP) kjer lahko podrazred podeduje iz več kot enega nadrazreda. Z drugimi besedami, otroški razred ima lahko več staršev.

Spodnja slika prikazuje slikovni prikaz več dediščin.

V zgornjem diagramu, razred C ima razred A in razred B kot njegovi starši.

Če upoštevamo resnični scenarij, otrok podeduje od očeta in matere. Tako je lahko otrok predstavljen kot izpeljani razred z "očetom" in "materjo" kot starši. Podobno imamo lahko veliko takšnih primerov večkratnega dedovanja v resničnem življenju.

Pri večkratnem dedovanju se konstruktorji podedovanega razreda izvajajo v vrstnem redu, v katerem so podedovani. Po drugi strani se destruktorji izvajajo v obratnem vrstnem redu njihove dedovanja.

Zdaj pa ponazorimo več dedovanja in preverimo vrstni red gradnje in uničenja predmetov.

Koda Ilustracija večkratnega dedovanja

Za ponazoritev večkratnega dedovanja smo zgornjo predstavitev natančno programirali v C ++. Koda za program je navedena spodaj.

#vključi
z uporabo imenskega prostora std;
razred A // osnovni razred A s konstruktorjem in destruktorjem
{
javno:
A () {cout << "razred A:: Konstruktor" << endl; }
~ A () {cout << "razred A:: Destruktor" << endl; }
};
razred B // osnovni razred B s konstruktorjem in destruktorjem
{
javno:
B () {cout << "razred B:: Konstruktor" << endl; }
~ B () {cout << "razred B:: Destruktor" << endl; }
};
razred C: javni B, javni A // izpeljani razred C podeduje razred A in nato razred B (upoštevajte vrstni red)
{
javno:
C () {cout << "razred C:: Konstruktor" << endl; }
~ C () {cout << "razred C:: Destruktor" << endl; }
};
int main () {
C c;
vrnitev 0;
}

Rezultat, ki ga dobimo iz zgornjega programa, je naslednji:

razred B:: Konstruktor
razred A:: Konstruktor
razred C:: Konstruktor
razred C:: Destruktor
razred A:: Destruktor
razred B:: Destruktor

Če preverimo izhod, vidimo, da so konstruktorji poklicani po vrstnem redu B, A in C, medtem ko so destruktorji v obratnem vrstnem redu. Zdaj, ko poznamo osnove večkratnega dedovanja, nadaljujemo z razpravo o diamantnem problemu.

Diamantni problem, razložen

Diamantni problem nastane, ko podrejeni razred podeduje od dveh starševskih razredov, ki imata oba skupni razred starih staršev. To je prikazano na spodnjem diagramu:

Tukaj imamo razred Otrok dedovanje po razredih Oče in Mati. Ta dva razreda pa razred podedujeta Oseba ker sta oče in mati osebnost.

Kot je prikazano na sliki, razred Otrok dvakrat podeduje lastnosti razreda Oseba - enkrat od Očeta in spet od Matere. To povzroča dvoumnost, saj prevajalnik ne razume, v katero smer naj gre.

Ta scenarij ustvarja graf dedovanja v obliki diamanta in se imenuje "Diamantni problem".

Kodirana ilustracija problema diamanta

Spodaj smo programsko predstavili zgornji primer dedovanja v obliki romba. Koda je podana spodaj:

#vključi
z uporabo imenskega prostora std;
razred Oseba {// razred Oseba
javno:
Oseba (int x) {cout << "Oseba:: Oseba (int) imenovana" << endl; }
};
razred Oče: javna oseba {// razred Oče podeduje osebo
javno:
Oče (int x): Oseba (x) {
cout << "Oče:: Oče (int) imenovan" << endl;
}
};
razred Mati: javna oseba {// razred Mama podeduje osebo
javno:
Mati (int x): oseba (x) {
cout << "Mati:: Mati (int) imenovana" << endl;
}
};
razred Otrok: javni oče, javna mati {// Otrok podeduje očeta in mamo
javno:
Otrok (int x): Mati (x), Oče (x) {
cout << "Otrok:: Otrok (int) imenovan" << endl;
}
};
int main () {
Otrok otrok (30);
}

Izhod tega programa je naslednji:

Oseba:: Klicana oseba (int)
Oče:: Klical je oče (int)
Oseba:: Klicana oseba (int)
Mati:: Klicana mati (int)
Otrok:: Otrok (int) poklican

Zdaj lahko tukaj vidite nejasnost. Konstruktor razreda Oseba se pokliče dvakrat: enkrat, ko je ustvarjen predmet razreda Oče, in naslednjič, ko je ustvarjen predmet razreda Mati. Lastnosti razreda Person se podedujejo dvakrat, kar povzroča dvoumnost.

Ker se konstruktor razreda Person pokliče dvakrat, se destruktor pokliče tudi dvakrat, ko se uniči predmet razreda Child.

Zdaj, če ste pravilno razumeli težavo, se pogovorimo o rešitvi problema diamanta.

Kako odpraviti problem diamanta v C ++

Rešitev problema diamanta je uporaba virtualno ključna beseda. Iz dveh starševskih razredov (ki dedujeta iz istega razreda starih staršev) naredimo virtualne razrede, da se izognemo dve kopiji razreda starih staršev v razredu otrok.

Spremenite zgornjo sliko in preverite rezultat:

Ilustracija kode za odpravo težave z diamanti

#vključi
z uporabo imenskega prostora std;
razred Oseba {// razred Oseba
javno:
Oseba () {cout << "Oseba:: Oseba () imenovana" << endl; } // Osnovni konstruktor
Oseba (int x) {cout << "Oseba:: Oseba (int) imenovana" << endl; }
};
razred Oče: virtualna javna oseba {// razred Oče podeduje osebo
javno:
Oče (int x): Oseba (x) {
cout << "Oče:: Oče (int) imenovan" << endl;
}
};
razred Mati: virtualna javna oseba {// razred Mama podeduje osebo
javno:
Mati (int x): oseba (x) {
cout << "Mati:: Mati (int) imenovana" << endl;
}
};
razred Otrok: javni oče, javna mati {// razred Otrok podeduje očeta in mamo
javno:
Otrok (int x): Mati (x), Oče (x) {
cout << "Otrok:: Otrok (int) imenovan" << endl;
}
};
int main () {
Otrok otrok (30);
}

Tukaj smo uporabili virtualno ključna beseda, ko razreda Oče in Mati podedujeta razred Oseba. To se običajno imenuje "virtualno dedovanje", ki zagotavlja, da se posreduje le en primerek podedovanega razreda (v tem primeru razreda Person).

Z drugimi besedami, razred Otrok bo imel en sam primerek razreda Oseba, ki si ga bosta delila razreda Oče in Mati. Nejasnosti se rešijo z enim primerkom razreda Person.

Izhod zgornje kode je podan spodaj:

Oseba:: Klicana oseba ()
Oče:: Klical je oče (int)
Mati:: Klicana mati (int)
Otrok:: Otrok (int) poklican

Tu lahko vidite, da se konstruktor razreda Oseba pokliče le enkrat.

Pri virtualnem dedovanju je treba omeniti, da tudi če je parametrizirani konstruktor datoteke Konstruktorji razreda Oče in mati z inicializacijo izrecno kličejo razred osebe seznami, poklican bo samo osnovni konstruktor razreda Person.

To je zato, ker obstaja samo en primerek navideznega osnovnega razreda, ki si ga deli več razredov, ki ga podedujejo.

Če želite preprečiti, da se osnovni konstruktor večkrat zažene, konstruktor za navidezni osnovni razred ne pokliče razreda, ki ga podeduje. Namesto tega konstruktor pokliče konstruktor betonskega razreda.

V zgornjem primeru razred Child neposredno pokliče osnovni konstruktor razreda Person.

Povezano: Vodnik za začetnike po knjižnici standardnih predlog v C ++

Kaj pa, če morate izvesti parametriziran konstruktor osnovnega razreda? To lahko storite tako, da ga izrecno pokličete v razred otrok, ne pa v razred Oče ali Mati.

Diamantni problem v C ++, rešen

Diamantni problem je dvoumnost, ki se pojavi pri večkratnem dedovanju, ko dva starševska razreda podedujeta od istega razreda starih staršev, oba starševska razreda pa podeduje en sam podrejeni razred. Brez uporabe virtualnega dedovanja bi podrejeni razred dvakrat podedoval lastnosti razreda starih staršev, kar bi povzročilo dvoumnost.

To se lahko v kodi v resničnem svetu pogosto pojavi, zato je pomembno, da se te nejasnosti odpravimo, kadar koli jih opazimo.

Diamantni problem je odpravljen z navideznim podedovanjem, pri katerem je virtualno ključna beseda se uporablja, ko starševski razredi podedujejo od razreda starih staršev v skupni rabi. S tem je narejena samo ena kopija razreda starih staršev, konstrukcijo objekta razreda starih staršev pa opravi podrejeni razred.

DelitiCvrkutatiE-naslov
10 najboljših začetnih projektov za nove programerje

Bi se radi naučili programiranja, pa ne veste, kje začeti? Ti začetniški programi in vaje vas bodo začeli.

Preberite Naprej

Sorodne teme
  • Programiranje
  • C Programiranje
O avtorju
Osebje MUO

Naročite se na naše novice

Pridružite se našemu glasilu za tehnične nasvete, ocene, brezplačne e -knjige in ekskluzivne ponudbe!

Kliknite tukaj, če se želite naročiti