Flere arv i C ++ er kraftfuldt, men et vanskeligt værktøj, der ofte fører til problemer, hvis det ikke bruges omhyggeligt - problemer som Diamond Problem.
I denne artikel vil vi diskutere diamantproblemet, hvordan det opstår ved flere arv, og hvad du kan gøre for at løse problemet.
Flere arv i C ++
Flere arv er en funktion ved objektorienteret programmering (OOP) hvor en underklasse kan arve fra mere end én superklasse. Med andre ord kan en børneklasse have mere end én forælder.
Nedenstående figur viser en billedlig fremstilling af flere arv.
I diagrammet ovenfor, klasse C har klasse A og klasse B som dets forældre.
Hvis vi overvejer et virkeligt scenario, arver et barn fra sin far og mor. Så et barn kan repræsenteres som en afledt klasse med "Far" og "Mor" som sine forældre. På samme måde kan vi have mange sådanne virkelige eksempler på flere arv.
I flere arv udføres konstruktørerne af en arvet klasse i den rækkefølge, de arves. På den anden side henrettes destruktører i omvendt rækkefølge af deres arv.
Lad os nu illustrere den multiple arv og kontrollere rækkefølgen af konstruktion og ødelæggelse af objekter.
Kodeillustration af flere arv
Til illustrationen med flere arv har vi nøjagtigt programmeret ovenstående repræsentation i C ++. Koden til programmet er angivet nedenfor.
#omfatte
ved hjælp af navneområde std;
klasse A // basisklasse A med konstruktor og destruktor
{
offentlig:
A () {cout << "klasse A:: Constructor" << endl; }
~ A () {cout << "klasse A:: Destructor" << endl; }
};
klasse B // basisklasse B med konstruktor og destruktor
{
offentlig:
B () {cout << "klasse B:: Constructor" << endl; }
~ B () {cout << "klasse B:: Destructor" << endl; }
};
klasse C: offentlig B, offentlig A // afledt klasse C arver klasse A og derefter klasse B (bemærk rækkefølgen)
{
offentlig:
C () {cout << "klasse C:: Constructor" << endl; }
~ C () {cout << "klasse C:: Destructor" << endl; }
};
int main () {
C c;
returnere 0;
}
Output vi får fra ovenstående program er som følger:
klasse B:: Konstruktør
klasse A:: Konstruktør
klasse C:: Konstruktør
klasse C:: Destructor
klasse A:: Destructor
klasse B:: Destructor
Hvis vi nu kontrollerer output, ser vi, at konstruktørerne kaldes i rækkefølge B, A og C, mens destruktorerne er i den modsatte rækkefølge. Nu hvor vi kender det grundlæggende ved multipel arv, går vi videre til at diskutere diamantproblemet.
Diamantproblemet, forklaret
Diamantproblemet opstår, når en børneklasse arver fra to forældreklasser, der begge deler en fælles bedsteforældreklasse. Dette er illustreret i diagrammet herunder:
Her har vi en klasse Barn arver fra klasser Far og Mor. Disse to klasser arver til gengæld klassen Person fordi både far og mor er person.
Som det fremgår af figuren, arver klassebarn karakterpersonerne to gange - en gang fra far og igen fra mor. Dette giver anledning til uklarhed, da kompilatoren ikke forstår, hvilken vej man skal gå.
Dette scenario giver anledning til en diamantformet arvegraf og kaldes berømt "Diamantproblemet."
Kodeillustration af diamantproblemet
Nedenfor har vi repræsenteret ovenstående eksempel på diamantformet arv programmatisk. Koden er angivet herunder:
#omfatte
ved hjælp af navneområde std;
klasse Person {// klasse Person
offentlig:
Person (int x) {cout << "Person:: Person (int) kaldet" << endl; }
};
klasse Far: offentlig person {// klasse far arver person
offentlig:
Far (int x): Person (x) {
cout << "Far:: Far (int) kaldet" << endl;
}
};
klasse Mor: offentlig person {// klasse Mor arver Person
offentlig:
Mor (int x): Person (x) {
cout << "Mor:: Mor (int) kaldet" << endl;
}
};
klasse Barn: offentlig far, offentlig mor {// Barn arver far og mor
offentlig:
Barn (int x): Mor (x), Far (x) {
cout << "Barn:: Barn (int) kaldet" << endl;
}
};
int main () {
Barnebarn (30);
}
Følgende er output fra dette program:
Person:: Person (int) kaldet
Far:: Far (int) kaldet
Person:: Person (int) kaldet
Mor:: Mor (int) kaldet
Barn:: Barn (int) kaldet
Nu kan du se tvetydigheden her. Personklasse -konstruktøren kaldes to gange: én gang, når Fader -klasseobjektet oprettes, og det næste, når moderklasseobjektet oprettes. Personklassens egenskaber arves to gange, hvilket giver anledning til uklarhed.
Da Person -klasse -konstruktøren kaldes to gange, vil destruktoren også blive kaldt to gange, når objektet i Child -klasse destrueres.
Hvis du nu har forstået problemet korrekt, lad os diskutere løsningen på diamantproblemet.
Sådan løses diamantproblemet i C ++
Løsningen på diamantproblemet er at bruge virtuel nøgleord. Vi laver de to forældreklasser (som arver fra samme bedsteforældreklasse) til virtuelle klasser for at undgå to kopier af bedsteforældreklassen i børneklassen.
Lad os ændre ovenstående illustration og kontrollere output:
Kodeillustration til løsning af diamantproblemet
#omfatte
ved hjælp af navneområde std;
klasse Person {// klasse Person
offentlig:
Person () {cout << "Person:: Person () kaldet" << endl; } // Grundkonstruktør
Person (int x) {cout << "Person:: Person (int) kaldet" << endl; }
};
klasse far: virtuel offentlig person {// klasse far arver person
offentlig:
Far (int x): Person (x) {
cout << "Far:: Far (int) kaldet" << endl;
}
};
klasse Mor: virtuel offentlig person {// klasse Mor arver Person
offentlig:
Mor (int x): Person (x) {
cout << "Mor:: Mor (int) kaldet" << endl;
}
};
klasse Barn: offentlig far, offentlig mor {// klasse Barn arver far og mor
offentlig:
Barn (int x): Mor (x), Far (x) {
cout << "Barn:: Barn (int) kaldet" << endl;
}
};
int main () {
Barnebarn (30);
}
Her har vi brugt virtuel nøgleord, når klasser Far og mor arver personklassen. Dette kaldes normalt "virtuel arv", hvilket garanterer, at kun en enkelt forekomst af den arvede klasse (i dette tilfælde personklassen) videregives.
Med andre ord vil Child -klassen have en enkelt forekomst af Person -klassen, delt af både Fader- og Moder -klasser. Ved at have en enkelt forekomst af Person -klassen løses uklarheden.
Outputtet af ovenstående kode er angivet nedenfor:
Person:: Person () kaldet
Far:: Far (int) kaldet
Mor:: Mor (int) kaldet
Barn:: Barn (int) kaldet
Her kan du se, at klassen Person -konstruktør kun kaldes én gang.
En ting at bemærke om virtuel arv er, at selvom den parameteriserede konstruktør af Personklasse kaldes eksplicit af far og mor klasse konstruktører gennem initialisering lister, kun basiskonstruktøren af Person -klassen vil blive kaldt.
Dette skyldes, at der kun er en enkelt forekomst af en virtuel baseklasse, der deles af flere klasser, der arver fra den.
For at forhindre, at basiskonstruktøren kører flere gange, kaldes konstruktøren for en virtuel baseklasse ikke af klassen, der arver fra den. I stedet kaldes konstruktøren af konstruktøren af betonklassen.
I eksemplet ovenfor kalder klassen Child direkte til basiskonstruktøren for klassepersonen.
Relaterede: En begyndervejledning til standardskabelonbiblioteket i C ++
Hvad hvis du har brug for at udføre den parameteriserede konstruktør af basisklassen? Du kan gøre det ved eksplicit at kalde det i klassen Børn frem for Fader eller Moder.
Diamantproblemet i C ++, løst
Diamantproblemet er en tvetydighed, der opstår i flere arv, når to forældreklasser arver fra den samme bedsteforældreklasse, og begge forældreklasser arves af en enkelt barneklasse. Uden at bruge virtuel arv ville barneklassen arve bedsteforældreklassens egenskaber to gange, hvilket førte til tvetydighed.
Dette kan dukke op ofte i den virkelige verden, så det er vigtigt at tage fat på den tvetydighed, når det bliver opdaget.
Diamantproblemet løses ved hjælp af virtuel arv, hvor virtuel søgeord bruges, når forældreklasser arver fra en delt bedsteforældreklasse. Ved at gøre det laves kun en kopi af bedsteforældreklassen, og opbygningen af bedsteforældreklassen udføres af børneklassen.
Vil du lære programmering, men ved ikke, hvor du skal starte? Disse programmeringsprojekter og selvstudier for begyndere starter dig.
Læs Næste
- Programmering
- C Programmering
Abonner på vores nyhedsbrev
Tilmeld dig vores nyhedsbrev for at få tekniske tips, anmeldelser, gratis e -bøger og eksklusive tilbud!
Klik her for at abonnere