inheritance c
Betydningen af arv i C ++ med eksempler:
Arv er et af de vigtigste træk ved objektorienteret programmering.
Arv er den teknik, hvormed en klasse erhverver egenskaberne og metoderne i en anden klasse. På denne måde kan vi genbruge den kode, der allerede er skrevet og verificeret. Klassen, der erhverver egenskaberne for en anden klasse, kaldes underklassen eller afledt klasse eller underklasse.
Klassen, hvis egenskaber erhverves, kaldes basisklassen eller forældreklassen eller superklassen. Når en klasse erhverver eller arver en anden klasse, så er alle baseklassens egenskaber og metoder tilgængelige for den afledte klasse, så vi kan genbruge denne kode.
=> Besøg her for at lære C ++ fra bunden.
hvordan man åbner en xml-fil i word
Hvad du lærer:
- Hvorfor har vi brug for arv?
- Arvemetoder
- Rækkefølge af konstruktører / ødelæggere i arv
- Typer af arv
- Skabelonarv
- Sammensætning
- Hvordan skal vi beslutte mellem sammensætning og arv?
- Konklusion
- Anbefalet læsning
Hvorfor har vi brug for arv?
Overvej en gruppe køretøjer som bil, bus, jeep osv. Hver af disse køretøjer har egenskaber og metoder som angivet i nedenstående diagram.
Hvis det kræves, at vi implementerer individuelle klasser til ovennævnte køretøjer, kan vi se, at i alle de tre klasser bliver vi nødt til at skrive den samme kode, da alle de tre køretøjstyper mere eller mindre udviser de samme egenskaber. Dette vil gøre vores program ineffektivt og besværligt, da der vil være en masse duplikatkode.
I stedet for at skrive en duplikeret kode som ovenfor, kan vi implementere funktionen af arv for at forhindre koden i at duplikere og også skrive et enkelt stykke kode og bruge det i alle de tre klasser. Dette er billedmæssigt repræsenteret som nedenfor.
I ovenstående figur har vi defineret en basisklasse 'Vehicles' og afledt klasserne Car, Bus og Jeep fra denne klasse. De almindelige metoder og egenskaber er en del af køretøjsklassen nu. Da andre klasser stammer fra køretøjsklassen, erhverver alle klasser disse metoder og egenskaber.
Derfor er vi bare nødt til at skrive den fælles kode kun én gang og alle tre klasser; Bil, bus og jeep erhverver det.
Således er den største fordel, vi får ved at arve de eksisterende klasser eller designe arvemekanisme, at genanvendelighed af kode er.
Yderligere læsning = >> Java-arvevejledning
Det generelle format til at arve en klasse er:
class derived_classname: access_specifier base_classname { };
Her ' afledt_klassnavn ”Er navnet på den afledte klasse,“ adgangsspecifikator 'Er adgangstilstand dvs. offentlig, beskyttet eller privat, hvor den afledte klasse skal arve basisklassen og' afledt_klassnavn ”Er navnet på basisklassen, som den afledte klasse arver fra.
Arvemetoder
'Access_specifier' vist i ovenstående arvedeklaration kan have deres værdier som vist nedenfor.
Afhængig af den specificerede access_specifier, når vi arver klassen, har vi forskellige arvemetoder som angivet nedenfor.
Offentlig arv
Generel syntaks
class sub_class : public parent_class
Når specificeringsadgangspecifikator er angivet, arves de offentlige medlemmer af baseklassen som offentlige, mens beskyttede medlemmer er beskyttet. Private medlemmer forbliver private. Dette er den mest populære arvemåde.
Privat arv
Generel syntaks
class sub_class : parent_class
Privat arv arver ikke noget. Når privat adgangsspecifikator bruges, bliver offentlige og beskyttede medlemmer af basisklassen også private.
Beskyttet arv
Generel syntaks
class sub_class:protected parent_class
Når der anvendes beskyttet adgangsspecifikator, bliver offentlige og beskyttede medlemmer af basisklassen beskyttede medlemmer i den afledte klasse.
Bemærk, at når vi bruger privat adgangsspecifikator til baseklassen, arves ingen af baseklassemedlemmerne. De bliver alle private i den afledte klasse.
Nedenfor er den tabelformede repræsentation af alle adgangstilstande og deres fortolkning for arv.
Afledt klasse -> Basis klasse | Privat | Offentlig | Beskyttet |
---|---|---|---|
Privat | Ikke arvet | Ikke arvet | Ikke arvet |
Offentlig | Privat | Offentlig | Beskyttet |
Beskyttet | Privat | Beskyttet | Beskyttet |
Rækkefølge af konstruktører / ødelæggere i arv
Når klasser arves, kaldes konstruktørerne i samme rækkefølge som klasserne arves. Hvis vi har en basisklasse og en afledt klasse, der arver denne basisklasse, kaldes basisklassekonstruktøren (hvad enten den er standard eller er parametreret) først efterfulgt af den afledte klassekonstruktør.
Følgende program viser rækkefølgen af konstruktører i arv. Vi har en baseklasse 'Base', som har en standardkonstruktør og en parametreret konstruktør. Vi udleder en klasse fra dette kaldet 'Derived', som også har en standard og en anden parameteriseret konstruktør.
Outputtet fra dette program viser rækkefølgen, som konstruktørerne kaldes til.
#include using namespace std; //order of execution of constructors in inheritance class Base { int x; public: // default constructor Base() { cout Produktion:
Grundkonstruktør til baseklasse
Grundkonstruktør til baseklasse
Afledt klasses standardkonstruktør
Basisklasse parametreret konstruktør
Afledt klasseparameteriseret konstruktør
Vi ser, at efter oprettelse af basisklasseobjektet opretter vi et afledt klasseobjekt med en standardkonstruktør. Når dette objekt oprettes, kaldes basisklassens standardkonstruktør først, og derefter udføres den afledte klassekonstruktør.
Tilsvarende, når det afledte klasseobjekt oprettes ved hjælp af den parametriserede konstruktør, kaldes den baserede klasseparameteriserede konstruktør først, og derefter kaldes den afledte klassekonstruktør.
Bemærk, at hvis der ikke var nogen parametreret konstruktør i baseklassen, ville standardkonstruktøren være blevet kaldt selv til at konstruere det parametriserede afledte klasseobjekt.
Men spørgsmålet er fortsat, hvorfor grundklassekonstruktør kaldes, mens man konstruerer de afledte klasseobjekter?
Vi ved, at en konstruktør bruges til at skabe objekter i klassen og også til at initialisere klassens medlemmer. Når det afledte klasseobjekt oprettes, har dets konstruktør kun kontrol over de afledte klassemedlemmer.
Den afledte klasse arver imidlertid også medlemmerne af baseklassen. Hvis kun den afledte klassekonstruktør blev kaldt, ville baseklassemedlemmerne arvet af den afledte klasse ikke blive initialiseret korrekt.
c ++ sleep_for
Som et resultat oprettes ikke hele objektet effektivt. Dette er grunden til, at alle basisklassekonstruktører kaldes først, når et afledt klasseobjekt oprettes.
Typer af arv
Afhængigt af den måde, hvorpå klassen er afledt, eller hvor mange baseklasser en klasse arver, har vi følgende arvetyper som vist i nedenstående figur.

Vi vil udforske hver af disse typer i vores næste tutorial om 'Typer af arv'.
Skabelonarv
Når vores implementering involverer skabeloner, skal vi arve eller stamme fra skabelonklasser, og vi bruger skabelonarv der.
Lad os direkte springe til et programmeringseksempel for bedre at forstå arven ved hjælp af skabeloner.
#include using namespace std; //template inhertance templateclass basecls_Template { public: T value; basecls_Template(T value) { this->value = value; } void displayVal() { cout << value << endl; } }; //derived class inherits basecls_Template class derivedcls_Child : public basecls_Template { public: derivedcls_Child(/* no parameters */): basecls_Template( 0 ){ // default char is NULL; } derivedcls_Child(char c): basecls_Template( c ) { ; } void displayVal_drvd() { displayVal(); } }; int main() { basecls_Template obj( 100 ); derivedcls_Child obj1( 'A' ); cout<<'basecls_Template obj = '; obj.displayVal(); // should print '100' cout< Produktion:
basecls_Template obj = 100
derivatedcls_Child obj1 (nedarvet fra basecls_Template = A
I ovenstående program har vi en skabelon med navnet basecls_Template, der definerer klasseskabelonen til baseklassen. Dernæst definerer vi en klasse afledtcls_Child, som vi vil udlede fra en skabelonklasse.
Men bemærk, at klassen basecls_Template kun er en type og ikke en klasse. Derfor kan vi ikke udlede klassen derivatedcls_Child fra denne skabelon.
Derfor, hvis vi erklærer barneklassen som:
class derivedcls_Child : public basecls_Template
Dette vil resultere i en fejl. Årsagen til at være basecls_Template er en datatype og ikke klasse. For at kunne arve medlemmerne af basecls_Template, skal vi først instansiere det, før vi stammer fra det.
Derfor er ovenstående erklæring, Klasse afledtcls_Child: public basecls_Template fungerer fint.
I denne erklæring har vi instantificeret skabelonen basecls_Template til en karakterklasseskabelon. Når vi først har brugt denne instantierede skabelonklasse, falder de andre ting, der følger, som at oprette og bruge objekter sammen med den sædvanlige arvearbejde.
Sammensætning
Indtil videre har vi set alt om arveforhold. Arv skildrer grundlæggende den slags forhold, hvor forholdet angiver en del. For eksempel, en slange er en slags krybdyr. Vi kan også sige, at krybdyr er en del af dyreklassen.
Afslutningsvis angiver arv 'ER EN' slags forhold, hvor vi kan sige, at den afledte klasse er en del af basisklassen.
Vi kan også repræsentere forhold som helhed. For eksempel, hvis vi siger, at lønklasse er en del af medarbejderklassen, repræsenterer vi den ikke korrekt. Vi ved, at medarbejdere har løn. Det er således mere bekvemt at sige ”Medarbejder har løn”.
Tilsvarende, hvis vi tager køretøjsklassen som et eksempel, kan vi sige, at køretøjet har motor, eller køretøjet har chassis. Således skildrer alle disse forhold 'HAR EN' relationer, der repræsenterer et helt objekt indeholdt i en anden klasse. Dette defineres som Sammensætning .
Forhold, der er afbildet af komposition, er afhængige af hinanden. For eksempel, et chassis kan ikke eksistere uden et køretøj. Tilsvarende kan løn ikke eksistere uden en medarbejder.
Vi kan repræsentere sammensætningen diagrammatisk som vist nedenfor:

Sammensætningen kaldes også indeslutning. I ovenstående repræsentation har vi vist en overordnet klasse. I modsætning til arv inkluderer vi et underordnet objekt i forældreklassen. Dette er indeslutning eller sammensætning.
hvad er en bin-fil?
Lad os tage et programmeringseksempel for at forstå dette.
#include using namespace std; //Composition example //Child class - address class Address { public: string houseNo, building, street, city, state; //Initialise the address object Address(string houseNo,string building,string street, string city, string state) { this->houseNo = houseNo; this->building = building; this->street = street; this->city = city; this->state = state; } }; //Parent class - Employee class Employee { private: Address* address; //composition->Employee has an address public: int empId; string empName; Employee(int empId, string empName, Address* address) { this->empId = empId; this->empName = empName; this->address = address; } void display() { cout< Produktion:
10001 Ved
A-101 Silver Springs Aundh Pune Maharashtra
I dette eksempel har vi en overordnet klasse medarbejder og en underordnet klasse adresse. Inde i forældreklassen Medarbejder har vi erklæret en markør til adresseklassen og initialiseret også dette objekt i medarbejderkonstruktøren. Således skildrer vi det forhold, at medarbejder har en adresse, der er sammensætning.
Hvordan skal vi beslutte mellem sammensætning og arv?
Komposition og arv skildrer begge forholdet mellem klasser. Mens arv skildrer “IS-A” -forholdet, viser sammensætningen “HAS-A” -forhold.
Nu er spørgsmålet, hvornår skal vi bruge arv, og hvornår skal vi bruge komposition? Faktisk kan vi ikke bestemme de nøjagtige situationer, som når vi skal bruge nogen af dem. Dette er fordi hver har sine egne fordele og ulemper.
Begge fremmer kode genanvendelighed. Arv kan gøre koden stor, da løsningerne bliver komplekse, men samtidig giver det os også mulighed for at udvide den eksisterende kode. Således skal vi bruge arv, når vores krav er at ændre og bruge egenskaberne og metoden til en anden klasse inden for den nye klasse.
Med andre ord, når vi vil tilføje flere egenskaber og udvide den eksisterende klasse. På den anden side, når vi ikke ønsker at ændre egenskaberne og adfærden for en anden klasse, men blot bruge den inde i klassen, går vi efter komposition.
Således er den bedste beslutning om, hvorvidt der skal bruges komposition eller arv, ved at afveje fordele og ulemper ved begge teknikker til den særlige situation.
= >> Læs også Komposition i Java
Konklusion
Således er vi kommet til slutningen af vores emne om arv. Vi har set forskellige former for arv. Vi har også set de typer arv, som vi vil udforske i vores næste tutorial. Vi lærte om rækkefølgen af konstruktører, der udføres i tilfælde af arv.
Vi studerede også om skabeloner og arv. Vi er nødt til at instantiere en skabelon, før vi kan bruge den til arv, da selve skabelonen er en datatype, og vi kan ikke arve fra en datatype.
Kompositionen er en anden type klasseforhold, og vi skal først kende den nøjagtige situation, og så kan vi kun beslutte, om vi vil bruge komposition eller arv.
I vores kommende vejledning vil vi se mere om arvetyperne.
=> Hold øje med den enkle C ++ træningsserie her.
Anbefalet læsning
- Typer af arv i C ++
- Runtime polymorfisme i C ++
- Venfunktioner i C ++
- Brug af Selen Select Class til håndtering af dropdown-elementer på en webside - Selen Tutorial # 13
- Klasser og objekter i C ++
- Statisk i C ++
- Unix Pipes Tutorial: Pipes in Unix Programming
- Java-interface og abstrakt klasseundervisning med eksempler