Daugkartinis paveldėjimas naudojant C ++ yra galingas, tačiau sudėtingas įrankis, kuris dažnai sukelia problemų, jei nėra kruopščiai naudojamas - tokių kaip deimantų problema.
Šiame straipsnyje aptarsime deimantų problemą, kaip ji atsiranda dėl daugybinio paveldėjimo ir ką galite padaryti, kad išspręstumėte problemą.
Daugkartinis paveldėjimas C ++
Keli paveldėjimai yra a Objektinio programavimo (OOP) ypatybė kur poklasis gali paveldėti iš daugiau nei vienos superklasės. Kitaip tariant, vaikų klasėje gali būti daugiau nei vienas iš tėvų.
Žemiau esančiame paveikslėlyje pavaizduotas kelių paveldėjimų vaizdinis vaizdas.
Aukščiau pateiktoje diagramoje C klasė turi A klasė ir B klasė kaip jos tėvai.
Jei atsižvelgsime į realaus gyvenimo scenarijų, vaikas paveldės iš savo tėvo ir motinos. Taigi vaiką galima pavaizduoti kaip išvestinę klasę, kurios tėvai yra „Tėvas“ ir „Motina“. Panašiai galime turėti daug tokių realaus gyvenimo daugialypio paveldėjimo pavyzdžių.
Daugkartinio paveldėjimo atveju paveldimos klasės konstruktoriai vykdomi tokia tvarka, kokia jie yra paveldimi. Kita vertus, naikintojai vykdomi atvirkštine jų paveldėjimo tvarka.
Dabar iliustruokime daugialypį paveldėjimą ir patikrinkime objektų statybos ir sunaikinimo tvarką.
Kodo paveldėjimo iliustracija
Kelių paveldėjimų iliustracijai mes tiksliai užprogramavome aukščiau pateiktą vaizdą C ++. Programos kodas pateiktas žemiau.
#įtraukti
naudojant vardų srities standartą;
A klasė // bazinė A klasė su konstruktoriumi ir destruktoriumi
{
viešas:
A () {cout << "A klasė:: Konstruktorius" << endl; }
~ A () {cout << "class A:: Destructor" << endl; }
};
B klasė // bazinė B klasė su konstruktoriumi ir naikintoju
{
viešas:
B () {cout << "B klasė:: Konstruktorius" << endl; }
~ B () {cout << "B klasė: Destructor" << endl; }
};
C klasė: vieša B, vieša A // išvesta C klasė paveldi A klasę, o paskui B klasę (atkreipkite dėmesį į tvarką)
{
viešas:
C () {cout << "C klasė:: Konstruktorius" << endl; }
~ C () {cout << "C klasė:: Destructor" << endl; }
};
int main () {
C c;
grįžti 0;
}
Rezultatas, kurį gauname iš aukščiau pateiktos programos, yra toks:
B klasė: konstruktorius
A klasė: konstruktorius
C klasė: konstruktorius
C klasė: naikintojas
A klasė: naikintojas
B klasė: naikintojas
Dabar, jei tikriname išvestį, matome, kad konstruktoriai vadinami B, A ir C tvarka, o destruktoriai - atvirkštine tvarka. Dabar, kai žinome daugialypio paveldėjimo pagrindus, pereiname prie Deimantų problemos aptarimo.
Deimantų problema, paaiškinta
Deimantinė problema atsiranda, kai vaikų klasė paveldi iš dviejų tėvų klasių, kurioms abiems būdinga bendra senelių klasė. Tai parodyta žemiau esančioje diagramoje:
Čia mes turime klasę Vaikas paveldi iš klasių Tėvas ir Motina. Šios dvi klasės savo ruožtu paveldi klasę Asmuo nes ir Tėvas, ir Motina yra Asmuo.
Kaip parodyta paveiksle, Vaiko klasė du kartus paveldi Asmens klasės bruožus - vieną kartą iš Tėvo ir dar kartą iš Motinos. Tai sukelia dviprasmybių, nes kompiliatorius nesupranta, kuriuo keliu eiti.
Šis scenarijus sukuria deimanto formos paveldėjimo grafiką ir yra žinomas kaip „Deimantų problema“.
Deimantinės problemos kodo iliustracija
Žemiau mes programiškai pateikėme aukščiau pateiktą deimanto formos paveldėjimo pavyzdį. Kodas pateiktas žemiau:
#įtraukti
naudojant vardų srities standartą;
klasės asmuo {// klasės asmuo
viešas:
Asmuo (int x) {cout << "Asmuo:: Asmuo (int) vadinamas" << endl; }
};
klasė Tėvas: viešas asmuo {// klasės tėvas paveldi asmenį
viešas:
Tėvas (int x): asmuo (x) {
cout << "Tėvas:: Tėvas (int) vadinamas" << endl;
}
};
klasė Motina: viešas asmuo {// klasė Motina paveldi Asmenį
viešas:
Motina (int x): asmuo (x) {
cout << "Motina:: Motina (int) vadinama" << endl;
}
};
klasė Vaikas: viešas Tėvas, vieša Motina {// Vaikas paveldi Tėvą ir Motiną
viešas:
Vaikas (int x): mama (x), tėvas (x) {
cout << "Vaikas:: Vaikas (int) vadinamas" << endl;
}
};
int main () {
Vaikas vaikas (30);
}
Toliau pateikiamas šios programos rezultatas:
Asmuo:: Asmuo (int) vadinamas
Tėvas:: Tėvas (int) paskambino
Asmuo:: Asmuo (int) vadinamas
Motina:: Motina (int) paskambino
Vaikas:: Vaikas (int) paskambino
Dabar čia galite pamatyti neaiškumus. Klasės konstruktorius asmeniui vadinamas du kartus: vieną kartą, kai sukuriamas Tėvo klasės objektas, ir kitą kartą, kai sukuriamas Motinos klasės objektas. Asmens klasės savybės paveldimos du kartus, todėl kyla neaiškumų.
Kadangi „Person“ klasės konstruktorius vadinamas du kartus, naikintojas taip pat bus iškviestas du kartus, kai bus sunaikintas „Child“ klasės objektas.
Dabar, jei teisingai supratote problemą, aptarkime Deimantinės problemos sprendimą.
Kaip išspręsti deimantų problemą naudojant C ++
Deimantų problemos sprendimas yra naudoti virtualus raktinis žodis. Dvi tėvų klases (paveldinčias iš tos pačios senelių klasės) paverčiame virtualiomis klasėmis, kad vaikų klasėje būtų išvengta dviejų senelių klasės egzempliorių.
Pakeiskite aukščiau pateiktą iliustraciją ir patikrinkite išvestį:
Kodo iliustracija deimantų problemai išspręsti
#įtraukti
naudojant vardų srities standartą;
klasės asmuo {// klasės asmuo
viešas:
Asmuo () {cout << "Asmuo:: Asmuo () vadinamas" << endl; } // Bazinis konstruktorius
Asmuo (int x) {cout << "Asmuo:: Asmuo (int) vadinamas" << endl; }
};
klasės Tėvas: virtualus viešas asmuo {// klasės tėvas paveldi asmenį
viešas:
Tėvas (int x): asmuo (x) {
cout << "Tėvas:: Tėvas (int) vadinamas" << endl;
}
};
klasė Motina: virtualus viešas asmuo {// klasė Motina paveldi Asmenį
viešas:
Motina (int x): asmuo (x) {
cout << "Motina:: Motina (int) vadinama" << endl;
}
};
klasė Vaikas: viešas Tėvas, vieša Motina {// klasė Vaikas paveldi Tėvą ir Motiną
viešas:
Vaikas (int x): mama (x), tėvas (x) {
cout << "Vaikas:: Vaikas (int) vadinamas" << endl;
}
};
int main () {
Vaikas vaikas (30);
}
Čia mes panaudojome virtualus raktinis žodis, kai klasės Tėvas ir Motina paveldi klasę Asmuo. Paprastai tai vadinama „virtualiu paveldėjimu“, kuris garantuoja, kad perduodamas tik vienas paveldėtos klasės egzempliorius (šiuo atveju - klasė „Asmuo“).
Kitaip tariant, Vaiko klasė turės vieną asmenybės klasės pavyzdį, kuriuo dalijasi ir Tėvo, ir Motinos klasės. Turint vieną asmenybės klasės egzempliorių, neaiškumai išsprendžiami.
Aukščiau pateikto kodo išvestis pateikta žemiau:
Asmuo:: Asmuo () paskambino
Tėvas:: Tėvas (int) paskambino
Motina:: Motina (int) paskambino
Vaikas:: Vaikas (int) paskambino
Čia galite pamatyti, kad klasės konstruktorius vadinamas tik vieną kartą.
Vienas dalykas, kurį reikia atkreipti dėmesį į virtualų paveldėjimą, yra tai, kad net jei parametrinis konstruktorius Tėvo ir motinos klasės konstruktoriai aiškiai inicijuoja asmeninę klasę sąrašus, bus iškviestas tik pagrindinis „Person“ klasės konstruktorius.
Taip yra todėl, kad yra tik vienas virtualios bazinės klasės egzempliorius, kurį dalijasi kelios iš jo paveldimos klasės.
Kad bazinis konstruktorius nebūtų paleistas kelis kartus, virtualios bazinės klasės konstruktorius nėra iškviečiamas iš jos paveldinčios klasės. Vietoj to konstruktorių kviečia betono klasės konstruktorius.
Anksčiau pateiktame pavyzdyje klasė „Child“ tiesiogiai iškviečia pagrindinį „Person“ konstruktorių.
Susijęs: Standartinės šablonų bibliotekos pradedantiesiems vadovas C ++
Ką daryti, jei reikia vykdyti bazinės klasės parametrinį konstruktorių? Tai galite padaryti aiškiai pavadinę jį Vaiko klasėje, o ne Tėvo ar Motinos klasėse.
Deimantų problema C ++, išspręsta
Deimantinė problema yra dviprasmybė, kylanti dėl daugybinio paveldėjimo, kai dvi tėvų klasės paveldi iš tos pačios senelių klasės, o abi tėvų klases paveldi viena vaikų klasė. Nenaudojant virtualiojo paveldėjimo, vaikų klasė du kartus paveldėtų senelių klasės savybes, o tai sukeltų neaiškumų.
Tai gali dažnai pasirodyti realaus pasaulio kode, todėl svarbu išspręsti šią dviprasmybę, kai ji pastebima.
Deimantų problema išspręsta naudojant virtualų paveldėjimą, kuriame virtualus raktinis žodis naudojamas, kai tėvų klasės paveldi iš bendrai naudojamų senelių klasės. Taip padaroma tik viena senelių klasės kopija, o senelių klasės objektų konstravimą atlieka vaikų klasė.
Nori išmokti programuoti, bet nežinai nuo ko pradėti? Šie pradedančiųjų programavimo projektai ir vadovėliai pradės jus.
Skaityti toliau
- Programavimas
- C programavimas
Prenumeruokite mūsų naujienlaiškį
Prisijunkite prie mūsų naujienlaiškio, kad gautumėte techninių patarimų, apžvalgų, nemokamų el. Knygų ir išskirtinių pasiūlymų!
Norėdami užsiprenumeruoti, spustelėkite čia