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.

instagram viewer

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.

RészvényCsipogEmail
A 10 legjobb kezdő projekt új programozóknak

Szeretnél megtanulni programozni, de nem tudod, hol kezdd? Ezek a kezdő programozási projektek és oktatóanyagok elindítanak.

Olvassa tovább

Kapcsolódó témák
  • Programozás
  • C Programozás
A szerzőről
MUO személyzet

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