inheritance c
Importanța moștenirii în C ++ cu exemple:
Moștenirea este una dintre cele mai importante caracteristici ale programării orientate pe obiecte.
Moștenirea este tehnica prin care o clasă dobândește proprietățile și metodele altei clase. Astfel putem reutiliza codul deja scris și verificat. Clasa care dobândește proprietățile altei clase se numește subclasă sau clasă derivată sau clasă copil.
Clasa ale cărei proprietăți sunt dobândite se numește clasa de bază sau clasa părinte sau superclasa. Când o clasă dobândește sau moștenește o altă clasă, atunci toate proprietățile și metodele clasei de bază sunt disponibile pentru clasa derivată, astfel încât să putem reutiliza acest cod.
=> Vizitați aici pentru a afla C ++ de la zero.
partiționarea echivalenței și analiza valorii la graniță
Ce veți învăța:
- De ce avem nevoie de moștenire?
- Moduri de moștenire
- Ordinul constructorilor / distrugătorilor în moștenire
- Tipuri de moștenire
- Moștenirea șablonului
- Compoziţie
- Cum ar trebui să decidem între compoziție și moștenire?
- Concluzie
- Lectură recomandată
De ce avem nevoie de moștenire?
Luați în considerare un grup de vehicule, cum ar fi mașina, autobuzul, jeep-ul etc. Fiecare dintre aceste vehicule va avea proprietăți și metode, așa cum sunt indicate în diagrama de mai jos.
Dacă ni se cere să implementăm clase individuale pentru vehiculele de mai sus, putem vedea că, în toate cele trei clase, va trebui să scriem același cod ca toate cele trei tipuri de vehicule care prezintă mai mult sau mai puțin aceleași proprietăți. Acest lucru va face programul nostru ineficient și greoi, deoarece va exista o mulțime de coduri duplicat.
În loc să scriem un cod duplicat ca mai sus, putem implementa caracteristica moștenirii pentru a împiedica duplicarea codului și, de asemenea, să scriem o singură bucată de cod și să o folosim în toate cele trei clase. Aceasta este reprezentată pictural ca mai jos.
În figura de mai sus, am definit o clasă de bază „Vehicule” și am derivat clasele Car, Bus și Jeep din această clasă. Metodele și proprietățile comune fac acum parte din clasa Vehicule. Deoarece alte clase sunt derivate din clasa Vehicule, toate clasele dobândesc aceste metode și proprietăți.
Prin urmare, trebuie doar să scriem codul comun o singură dată și toate cele trei clase; Mașina, autobuzul și jeep-ul vor achiziționa acest lucru.
Astfel, principalul avantaj pe care îl obținem prin moștenirea claselor existente sau prin proiectarea mecanismului de moștenire este reutilizarea codului.
Lecturi suplimentare = >> Tutorial de moștenire Java
Formatul general pentru moștenirea unei clase este:
class derived_classname: access_specifier base_classname { };
Aici ' derivat_classname ”Este numele clasei derivate,„ access_specifier 'Este modul de acces, adică public, protejat sau privat, în care clasa derivată trebuie să moștenească clasa de bază și' derivat_classname ”Este numele clasei de bază de la care moștenește clasa derivată.
Moduri de moștenire
„Access_specifier” afișat în declarația de moștenire de mai sus, poate avea valorile lor așa cum se arată mai jos.
În funcție de specificatorul de acces specificat atunci când moștenim clasa, avem diferite moduri de moștenire așa cum sunt enumerate mai jos.
Moștenirea publică
Sintaxa generală
class sub_class : public parent_class
Când este specificat un specificator de acces public, membrii publici ai clasei de bază sunt moșteniți ca public în timp ce membrii protejați sunt protejați. Membrii privați rămân privați. Acesta este cel mai popular mod de moștenire.
Moștenirea privată
Sintaxă generală
class sub_class : parent_class
Moștenirea privată nu moștenește nimic. Când se utilizează specificatorul de acces privat, membrii publici și protejați ai clasei de bază devin, de asemenea, private.
Moștenirea protejată
Sintaxă generală
class sub_class:protected parent_class
Când este utilizat un identificator de acces protejat, membrii publici și protejați ai clasei de bază devin membri protejați din clasa derivată.
Rețineți că atunci când folosim un identificator de acces privat pentru clasa de bază, niciunul dintre membrii clasei de bază nu este moștenit. Toate devin private în clasa derivată.
Mai jos este reprezentarea tabelată a tuturor modurilor de acces și interpretarea lor pentru moștenire.
Clasa derivată -> Clasa de bază | Privat | Public | Protejat |
---|---|---|---|
Privat | Nu moștenit | Nu moștenit | Nu moștenit |
Public | Privat | Public | Protejat |
Protejat | Privat | Protejat | Protejat |
Ordinul constructorilor / distrugătorilor în moștenire
Când clasele sunt moștenite, constructorii sunt chemați în aceeași ordine în care sunt moștenite clasele. Dacă avem o clasă de bază și o clasă derivată care moștenește această clasă de bază, atunci constructorul clasei de bază (indiferent dacă este implicit sau parametrizat) va fi numit mai întâi urmat de constructorul clasei derivate.
Următorul program demonstrează ordinea constructorilor în moștenire. Avem o clasă de bază „Base” care are un constructor implicit și un constructor parametrizat. Obținem o clasă din acest numit „Derivat” care are, de asemenea, un constructor implicit și altul parametrizat.
Ieșirea acestui program arată ordinea în care sunt numiți constructorii.
#include using namespace std; //order of execution of constructors in inheritance class Base { int x; public: // default constructor Base() { cout Ieșire:
Constructor implicit al clasei de bază
Constructor implicit al clasei de bază
Constructor implicit al clasei derivate
Constructor parametrizat din clasa de bază
Constructor parametrizat de clasă derivată
Vedem că după crearea obiectului de clasă de bază creăm un obiect de clasă derivat cu un constructor implicit. Când se creează acest obiect, se apelează mai întâi constructorul implicit al clasei de bază și apoi se execută constructorul clasei derivate.
În mod similar, atunci când obiectul de clasă derivat este creat folosind constructorul parametrizat, constructorul parametrizat al clasei de bază este numit mai întâi și apoi este chemat constructorul de clasă derivat.
Rețineți că dacă nu a existat un constructor parametrizat în clasa de bază, atunci constructorul implicit ar fi fost apelat chiar și pentru construirea obiectului clasei derivate parametrizate.
Dar rămâne întrebarea de ce este chemat constructorul clasei de bază în timp ce construim obiectele clasei derivate?
Știm că un constructor este folosit pentru a crea obiecte ale clasei și, de asemenea, pentru a inițializa membrii clasei. Când este creat obiectul de clasă derivat, constructorul său are control doar asupra membrilor clasei derivate.
Cu toate acestea, clasa derivată moștenește și membrii clasei de bază. Dacă s-a apelat doar constructorul clasei derivate, atunci membrii clasei de bază moștenite de clasa derivată nu ar fi inițializate corect.
expresie regulată în c ++
Ca urmare, întregul obiect nu va fi creat eficient. Acesta este motivul pentru care toți constructorii de clase de bază sunt numiți mai întâi atunci când este creat un obiect de clasă derivat.
Tipuri de moștenire
În funcție de modul în care este derivată clasa sau de câte clase de bază moștenește o clasă, avem următoarele tipuri de moștenire așa cum sunt descrise în figura de mai jos.

Vom explora fiecare dintre aceste tipuri în următorul nostru tutorial despre „Tipuri de moștenire”.
Moștenirea șablonului
Când implementarea noastră implică șabloane, atunci trebuie să moștenim sau să derivăm din clasele de șabloane și folosim moștenirea șablonului acolo.
Să trecem direct la un exemplu de programare pentru a înțelege mai bine moștenirea folosind șabloane.
#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< Ieșire:
basecls_Template obj = 100
derivcls_Child obj1 (moștenit de la basecls_Template = A
În programul de mai sus, avem un șablon numit basecls_Template care definește șablonul clasei pentru clasa de bază. Apoi, definim o clasă derivatcls_Child pe care dorim să o derivăm dintr-o clasă șablon.
Rețineți însă că clasa basecls_Template este doar un tip și nu o clasă. Prin urmare, nu putem deriva clasa derivcls_Child din acest șablon.
Prin urmare, dacă declarăm clasa copil ca:
class derivedcls_Child : public basecls_Template
Acest lucru va duce la o eroare. Motivul pentru care este bazecls_Template este un tip de date și nu o clasă. Astfel, pentru a moșteni membrii bazecls_Template, ar trebui mai întâi să-l instanțiem înainte să derivăm din el.
Prin urmare, afirmația de mai sus, Clasa provenităcls_Child: public basecls_Template Merge bine.
În această afirmație, am instanțiat șablonul basecls_Template într-un șablon de clasă de caractere. Odată ce am folosit această clasă de șablon instantaneat, celelalte lucruri care urmează, cum ar fi crearea și utilizarea obiectelor, coincid cu funcționarea obișnuită a moștenirii.
Compoziţie
Până acum am văzut totul despre relațiile de moștenire. Moștenirea descrie practic tipul de relații în care relația indică o parte. De exemplu, un șarpe este un fel de reptilă. Putem spune, de asemenea, că reptilele fac parte din clasa Animal.
În concluzie, moștenirea indică „IS-A” fel de relații în care putem spune că clasa derivată este o parte a clasei de bază.
De asemenea, putem reprezenta relațiile în ansamblu. De exemplu, dacă spunem că Clasa salarială face parte din clasa Angajați, atunci nu o reprezentăm corect. Știm că angajații au un salariu. Astfel, este mai convenabil să spui „Angajatul are un salariu”.
În mod similar, dacă luăm ca exemplu clasa Vehicule, putem spune că Vehiculul are motor sau Vehiculul are șasiu. Astfel, toate aceste relații descriu 'ARE O' relații care reprezintă un obiect întreg cuprins într-o altă clasă. Aceasta este definită ca Compoziţie .
Relațiile descrise de compoziție sunt dependente una de cealaltă. De exemplu, un șasiu nu poate exista fără un vehicul. În mod similar, salariul nu poate exista fără un angajat.
Putem reprezenta schematic compoziția așa cum se arată mai jos:

Compoziția este, de asemenea, denumită Izolare. În reprezentarea de mai sus, am arătat o clasă părinte. Spre deosebire de moștenire, includem un obiect de clasă copil în clasa părinte. Aceasta este izolare sau compoziție.
cum se creează un proiect Java în eclipsă
Să luăm un exemplu de programare pentru a înțelege acest lucru.
#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< Ieșire:
10001 Ved
A-101 Silver Springs Aundh Pune Maharashtra
În acest exemplu, avem o clasă părinte Angajat și o clasă copil Adresă. În cadrul clasei părinte Employee, am declarat un pointer la clasa Address și, de asemenea, inițializăm acest obiect în constructorul Employee. Astfel, prezentăm relația că angajatul are o adresă care este compoziția.
Cum ar trebui să decidem între compoziție și moștenire?
Compoziția și moștenirea descriu relațiile dintre clase. În timp ce moștenirea descrie relația „IS-A”, compoziția descrie relația „HAS-A”.
Acum întrebarea este că atunci când ar trebui să folosim moștenirea și când ar trebui să folosim compoziția? De fapt, nu putem decide cu privire la situațiile exacte ca atunci când ar trebui să le folosim pe oricare dintre ele. Acest lucru se datorează faptului că fiecare are propriile sale avantaje și dezavantaje.
Ambele promovează reutilizarea codului. Moștenirea poate face codul voluminos pe măsură ce soluțiile devin complexe, dar, în același timp, ne permite și extinderea codului existent. Astfel, ar trebui să folosim moștenirea atunci când cerința noastră este să modificăm și să folosim proprietățile și metoda altei clase din noua clasă.
Cu alte cuvinte, când dorim să adăugăm mai multe proprietăți și să extindem clasa existentă. Pe de altă parte, atunci când nu dorim să modificăm proprietățile și comportamentul altei clase, ci pur și simplu să o folosim în interiorul clasei, mergem pentru compoziție.
Astfel, cea mai bună decizie este dacă se folosește compoziția sau moștenirea se va lua prin cântărirea argumentelor pro și contra ambelor tehnici pentru situația particulară.
= >> De asemenea, citiți Compoziție în Java
Concluzie
Astfel, am ajuns la sfârșitul subiectului nostru despre moștenire. Am văzut diferite moduri de moștenire. De asemenea, am văzut tipurile de moștenire pe care le vom explora în următorul nostru tutorial. Am aflat despre ordinea constructorilor care sunt executați în caz de moștenire.
De asemenea, am studiat despre șabloane și moștenire. Trebuie să instanțiem un șablon înainte să îl putem folosi în moștenire, deoarece șablonul în sine este un tip de date și nu putem moșteni dintr-un tip de date.
Compoziția este un alt tip de relație de clasă și trebuie să știm mai întâi situația exactă și apoi numai noi putem decide dacă să folosim compoziția sau moștenirea.
În viitorul nostru tutorial, vom vedea mai multe despre tipurile de moștenire.
=> Urmăriți aici seria de antrenament C ++ simplă.
Lectură recomandată
- Tipuri de moștenire în C ++
- Polimorfism în timp de execuție în C ++
- Funcții prieten în C ++
- Utilizarea clasei Selenium Select pentru manipularea elementelor derulante pe o pagină web - Tutorial Selenium # 13
- Clase și obiecte în C ++
- Static în C ++
- Tutorial Unix Pipes: Pipe în programarea Unix
- Interfață Java și tutorial de clasă abstractă cu exemple