A C ++ többszörös öröklése hatékony, de trükkös eszköz, amely gyakran problémákhoz vezet, ha nem használják óvatosan - olyan problémákhoz, mint a Gyémánt probléma.
Ebben a cikkben megvitatjuk a Gyémánt -problémát, hogyan merül fel a többszörös öröklésből, és mit tehet a probléma megoldása érdekében.
Többszörös öröklődés C ++ nyelven
A többszörös öröklődés a az objektumorientált programozás (OOP) jellemzője ahol egy alosztály örökölhet több szuperosztályból. Más szóval, egy gyermekosztálynak több szülője is lehet.
Az alábbi ábra több öröklés képi ábrázolását mutatja.
A fenti diagramon C osztály van A osztály és B osztály mint a szülei.
Ha egy valós forgatókönyvet veszünk figyelembe, a gyermek örököl az apjától és az anyjától. Tehát egy gyermeket származtatott osztályként lehet ábrázolni, szülei „apa” és „anya”. Hasonlóképpen, sok ilyen valós példánk lehet a többszörös öröklésre.
Többszörös öröklés esetén az örökölt osztály konstruktőreit az öröklés sorrendjében hajtják végre. Másrészt a rombolókat öröklésük fordított sorrendjében hajtják végre.
Most szemléltessük a többszörös öröklődést, és ellenőrizzük az objektumok építésének és megsemmisítésének sorrendjét.
A többszörös öröklés kódillusztrációja
A többszörös öröklődés szemléltetéséhez pontosan programoztuk a fenti ábrázolást C ++ nyelven. A program kódja az alábbiakban található.
#befoglalni
névtér használata std;
osztály A // alaposztály A konstruktorral és destruktorral
{
nyilvános:
A () {cout << "class A:: Constructor" << endl; }
~ A () {cout << "A osztály:: Destructor" << endl; }
};
B osztály // B alaposztály konstruktorral és destruktorral
{
nyilvános:
B () {cout << "class B:: Constructor" << endl; }
~ B () {cout << "B osztály:: Destructor" << endl; }
};
C osztály: nyilvános B, nyilvános A // a származtatott C osztály örökli az A, majd a B osztályt (vegye figyelembe a sorrendet)
{
nyilvános:
C () {cout << "C osztály: Konstruktor" << endl; }
~ C () {cout << "C osztály:: Destructor" << endl; }
};
int main () {
C c;
visszatérés 0;
}
A fenti program eredménye a következő:
B osztály:: Konstruktor
A osztály:: Konstruktor
C osztály: Konstruktor
C osztály: Destructor
A osztály:: Destructor
B osztály:: Destructor
Ha most ellenőrizzük a kimenetet, látjuk, hogy a konstruktorokat B, A és C sorrendben hívják, míg a destruktorokat fordított sorrendben. Most, hogy ismerjük a többszörös öröklés alapjait, továbblépünk a Gyémánt -probléma tárgyalására.
A gyémánt probléma, magyarázva
A gyémánt probléma akkor jelentkezik, amikor egy gyermekosztály örököl két szülőosztálytól, akiknek közös a nagyszülő osztályuk. Ezt szemlélteti az alábbi diagram:
Itt van egy osztályunk Gyermek osztályoktól örökölve Apa és Anya. Ez a két osztály viszont örökli az osztályt Személy mert apa és anya is személy.
Amint az ábrán látható, a gyermekosztály kétszer örökli az osztály Személy vonásait - egyszer Apától, és ismét Anyától. Ez kétértelműséget okoz, mivel a fordító nem érti, hogy melyik úton kell haladnia.
Ez a forgatókönyv gyémánt alakú öröklési gráfot eredményez, és híres „Gyémánt probléma” -nak hívják.
A gyémánt probléma kódillusztrációja
Az alábbiakban a gyémánt alakú öröklődés fenti példáját mutattuk be programszerűen. A kódot az alábbiakban adjuk meg:
#befoglalni
névtér használata std;
osztály Személy {// osztály Személy
nyilvános:
Személy (int x) {cout << "Person:: Person (int) nevű" << endl; }
};
osztályapa: nyilvános személy {// osztályapa örököl személyt
nyilvános:
Apa (int x): személy (x) {
cout << "Apa:: Apa (int) hívott" << endl;
}
};
osztály Anya: nyilvános személy {// osztály anya örököl személyt
nyilvános:
Anya (int x): személy (x) {
cout << "Anya:: Anya (int) nevű" << endl;
}
};
osztály Gyermek: nyilvános apa, nyilvános anya {// A gyermek örökli apát és anyát
nyilvános:
Gyermek (int x): anya (x), apa (x) {
cout << "Gyermek:: Gyermek (int)" << endl;
}
};
int main () {
Gyermek gyermek (30);
}
A program kimenete a következő:
Személy:: Személy (int) hívott
Apa:: apa (int) hívott
Személy:: Személy (int) hívott
Anya:: Anya (int) hívott
Gyermek:: Gyermek (int) hívott
Most láthatja a kétértelműséget itt. A Személy osztály konstruktorát kétszer hívják meg: egyszer, amikor létrejön az Apa osztály objektum, és másodszor, amikor létrejön az Anya osztály objektum. A Személy osztály tulajdonságai kétszer öröklődnek, ami kétértelműséget okoz.
Mivel a Személy osztály konstruktorát kétszer hívják meg, a destruktor is kétszer lesz meghívva, amikor a Child osztályú objektum megsemmisül.
Most, ha helyesen értette a problémát, beszéljük meg a Gyémánt -probléma megoldását.
Hogyan javítsuk ki a gyémánt problémát C ++ nyelven
A gyémánt probléma megoldása a virtuális kulcsszó. A két szülőosztályt (akik ugyanattól a nagyszülő osztálytól örökölnek) virtuális osztályokká alakítjuk, hogy elkerüljük a nagyszülő osztály két példányát a gyermekosztályban.
Változtassuk meg a fenti ábrát, és ellenőrizzük a kimenetet:
Kódillusztráció a gyémánt probléma megoldásához
#befoglalni
névtér használata std;
osztály Személy {// osztály Személy
nyilvános:
Személy () {cout << "Person:: Person ()" << endl; } // Alapkonstruktor
Személy (int x) {cout << "Person:: Person (int) nevű" << endl; }
};
osztályapa: virtuális nyilvános személy {// osztályapa örököl személyt
nyilvános:
Apa (int x): személy (x) {
cout << "Apa:: Apa (int) hívott" << endl;
}
};
osztály Anya: virtuális nyilvános Személy {// osztály Anya örököl Személyt
nyilvános:
Anya (int x): személy (x) {
cout << "Anya:: Anya (int) nevű" << endl;
}
};
osztály Gyermek: nyilvános apa, nyilvános anya {// osztály Gyermek örököl apa és anya
nyilvános:
Gyermek (int x): anya (x), apa (x) {
cout << "Gyermek:: Gyermek (int)" << endl;
}
};
int main () {
Gyermek gyermek (30);
}
Itt használtuk a virtuális kulcsszó, amikor az osztályok Apa és Anya öröklik a Személy osztályt. Ezt általában „virtuális öröklődésnek” nevezik, amely garantálja, hogy az örökölt osztály egyetlen példánya (ebben az esetben a Személy osztály) kerül továbbadásra.
Más szóval, a Gyermek osztálynak egyetlen példánya lesz a Személy osztályból, amelyet az Apa és az Anya osztály is megoszt. A Személy osztály egyetlen példányával a kétértelműség megoldódik.
A fenti kód kimenete az alábbiakban található:
Személy:: Személy () hívott
Apa:: apa (int) hívott
Anya:: Anya (int) hívott
Gyermek:: Gyermek (int) hívott
Itt látható, hogy az osztály Személy konstruktorát csak egyszer hívják meg.
Egy dolgot meg kell jegyezni a virtuális öröklődéssel kapcsolatban, hogy még akkor is, ha a A személyosztályt az apa és anya osztály konstruktőrei az inicializálás révén kifejezetten hívják listák, csak a Személy osztály alapkonstruktorát hívják meg.
Ennek az az oka, hogy a virtuális alaposztálynak csak egyetlen példánya van, amelyet több osztály oszt meg, amelyek örökölnek belőle.
Annak érdekében, hogy az alapkonstruktor ne fusson többször, a virtuális alaposztály konstruktorát nem hívja meg az attól öröklődő osztály. Ehelyett a konstruktőrt a betonosztály konstruktőre hívja.
A fenti példában a Child osztály közvetlenül hívja meg az Person személy alapkonstruktorát.
Összefüggő: Kezdő útmutató a szabványos sablonkönyvtárhoz C ++ nyelven
Mi van, ha végre kell hajtania az alaposztály paraméterezett konstruktorát? Ezt úgy teheti meg, hogy kifejezetten a Gyermek osztályban nevezi, nem pedig az Apa vagy Anya osztályokban.
A gyémánt probléma C ++ nyelven, megoldva
A Gyémánt probléma egy kétértelműség, amely több öröklődés esetén merül fel, amikor két szülőosztály örököl ugyanabból a nagyszülő osztályból, és mindkét szülőosztályt egyetlen gyermekosztály örökli. Virtuális öröklés nélkül a gyermekosztály kétszer örökölné a nagyszülő osztály tulajdonságait, ami kétértelműséghez vezet.
Ez gyakran előfordulhat a valós kódban, ezért fontos, hogy ezt a kétértelműséget kezeljük, amikor észreveszik.
A gyémánt problémát virtuális örökléssel oldják meg, amelyben a virtuális kulcsszó akkor használatos, amikor a szülői osztályok örökölnek egy megosztott nagyszülő osztálytól. Ezzel a nagyszülő osztályból csak egy példány készül, és a nagyszülő osztály objektumkonstrukcióját a gyermekosztály végzi.
Szeretnél megtanulni programozni, de nem tudod, hol kezdd? Ezek a kezdő programozási projektek és oktatóanyagok elindítanak.
Olvassa tovább
- Programozás
- C Programozás
Iratkozzon fel hírlevelünkre
Csatlakozz hírlevelünkhöz, ahol technikai tippeket, értékeléseket, ingyenes e -könyveket és exkluzív ajánlatokat találsz!
Feliratkozáshoz kattintson ide