Sunteți pe pagina 1din 5

Curs 11: Moștenire

Moștenirea între clase


O caracteristică de bază a claselor C++ este moștenirea. Moștenirea permite să se creeze clase care sunt
derivate din alte clase, astfel încât aceste clase derivate să includă automat unii membrii ai clasei
"părinte", plus membrii proprii. De exemplu, vom presupune că dorim să declarăm o suită de clase care
descriu poligoane, cum ar fi CRectangle, sau CTriangle. Acestea toate au anumite proprietăți comune,
cum ar fi faptul că ambele pot fi descrise cu ajutorul a două dimensiuni: baza și înălțimea (width și
height).

Acest lucru ar putea fi reprezentat în lumea claselor printr-o clasă CPolygon din care am putea deriva
celelalte două: CRectangle și CTriangle.

Clasa CPolygon va conține membrii care sunt comuni pentru ambele tipuri de poligoane. În cazul
nostru: width și height. Iar CRectangle și CTriangle vor fi clasele derivate ale lui CPolygon, cu
caracteristici specifice care diferă de la un tip de poligon la celălalt.

Clasele care sunt derivate din alte clase moștenesc toți membrii clasei de bază. Acest lucru înseamnă
că dacă o clasă de bază include un membru A și din această clasă derivăm o altă clasă cu un alt membru
numit B, clasa derivată va conține atât membrul A cât și B.

Pentru a deriva o clasă dintr-o altă clasă se utilizează simbolul două puncte (:) în declarația clasei
derivate, folosind următorul format:

class numele_clasei_derivate: public numele_clasei_de_baza


{ /*...*/ };

Specificatorul de acces public folosit mai sus poate fi înlocuit cu oricare din ceilalți specificatori de
acces, protected sau private. Acest specificator de acces limitează cel mai accesibil nivel pentru
membrii moșteniți de la clasa de bază: Membrii cu un nivel mai accesibil decât acesta moștenesc acest
nivel de acces în locul aceluia. Iar membrii cu un nivel de acces egal sau mai restrictiv decât acesta își
păstrează nivelul lor de restricție în clasa derivată.

1
1 // derived classes 20
2 #include <iostream> 10
3 #include <conio.h>
4 using namespace std;
5
6 class CPolygon {
7 protected:
8 int width, height;
9 public:
10 void set_values (int a, int b)
11 { width=a; height=b;}
12 };
13
14 class CRectangle: public CPolygon {
15 public:
16 int area ()
17 { return (width * height); }
18 };
19
20 class CTriangle: public CPolygon {
21 public:
22 int area ()
23 { return (width * height / 2); }
24 };
25
26 int main () {
27 CRectangle rectang;
28 CTriangle trgl;
29 rectang.set_values (4,5);
30 trgl.set_values (4,5);
31 cout << rect.area() << endl;
32 cout << trgl.area() << endl;
33 _getch();
34 return 0;
35 }

Obiectele claselor CRectangle și CTriangle conțin fiecare membrii moșteniți de la CPolygon. Aceștia
sunt: width, height și set_values().

Specificatorul de acces protected este similar cu private. Singura diferență este chiar în legătură cu
moștenirea. Când o clasă e derivată dintr-o alta, membrii clasei derivate pot accesa membrii protejați
(protected) moșteniți de la clasa de bază, însă nu și membrii privați (private).

Deoarece am vrut ca width și height să fie accesibili membrilor din clasele derivate CRectangle și
CTriangle și nu doar membrilor lui CPolygon, am folosit accesul protected în loc de private.

2
Putem rezuma diferitele tipuri de acces funcție de cine poate avea acces la respectivii membrii precedați
de acești specificatori de acces, astfel:

Acces public protected private


Membrii aceleași clase da da da
Funcții si clase prietene da da da
Membrii claselor derivate da da nu
Ne-membri da nu nu

unde "ne-membri" reprezintă orice acces din afara clasei, cum ar fi din main(), dintr-o altă clasă sau
dintr-o funcție.

În exemplul nostru, membrii moșteniți de către CRectangle și CTriangle au aceleași permisii de acces
cum au avut în clasa lor de bază CPolygon:

1 CPolygon::width // acces protejat


2 CRectangle::width // acces protejat
3
4 CPolygon::set_values() // acces public
5 CRectangle::set_values() // acces public

Aceasta deoarece am folosit cuvântul-cheie public pentru a defini relația de moștenire pe fiecare din
clasele derivate:

class CRectangle: public CPolygon { ... }

Acest cuvânt-cheie public după simbolul două puncte (:) semnifică nivelul cel mai accesibil pe care-l
vor avea membrii derivați din clasa ce urmează după cuvântul-cheie (în acest caz CPolygon).
Deoarece public este nivelul cel mai accesibil, specificând acest cuvânt-cheie clasa derivată va moșteni
toți membrii cu aceleași niveluri de acces pe care le-au avut în clasa de bază.

Dacă specificăm niveluri de acces mai restrictive, cum ar fi protected, toți membrii publici ai clasei de
bază sunt moșteniți ca protejați (protected) în clasa derivată. Iar dacă specificăm nivelul de acces cel
mai restrictiv: private, toți membrii clasei de bază sunt moșteniți ca privați (private).

De exemplu, dacă fiica este o clasă derivată din parinte pe care am definit-o ca:

class fiica: protected parinte;

acest lucru ar seta protected ca nivelul maxim de acces pentru membrii clasei fiica pe care i-a moștenit
de la clasa parinte. Aceasta înseamnă că toți membrii care erau publici în parinte vor deveni protected
în fiica. Desigur, acest fapt nu va restricționa clasa fiica să-și declare proprii membri publici. Acest
nivel de acces maxim este setat doar pentru membrii moșteniți din clasa parinte.

3
Dacă nu specificăm explicit nici un nivel de acces pentru moștenire, compilatorul presupune acces
private pentru clase declarate cu cuvântul-cheie class și public pentru cele declarate cu struct.

Regulă: Utilizați moștenirea cu specificatorul de acces public dacă nu există vreun motiv special
pentru a face altfel!!!

Ce se moștenește de la clasa de bază?


În principiu, o clasă derivată moștenește orice membru al clasei de bază cu excepția:

 constructorului acesteia și a destructorului


 membrilor operatorului de asignare= si de asignare la copiere() a acesteia
 prietenilor acesteia

Cu toate că constructorii și destructorii clasei de bază nu se moștenesc, constructorul implicit (adică


acel constructor fără parametri) și destructorul sunt apelați întotdeauna când un nou obiect a clasei
derivate este creat sau distrus.

Dacă clasa de bază nu are un constructor implicit sau dacă doriți ca un constructor supraîncărcat să fie
apelat când se creează un nou obiect derivat, puteți specifica acest lucru în fiecare definiție a
constructorului din clasa derivată:

nume_constructor_derivat (parametri) : nume_constructor_baza (parametri) {...}

De exemplu:

1 // constructori si clase derivate parinte: fara parametri


2 #include <iostream> fiica: parametru int
3 #include <conio.h>
4 using namespace std; parinte: parametru int
5 fiu: parametru int
6 class parinte {
7 public:
8 parinte ()
9 { cout << "parinte: fara parametri\n"; }
10 parinte (int a)
11 { cout << "parinte: parametru int\n"; }
12 };
13
14 class fiica : public parinte {
15 public:
16 fiica (int a)
17 { cout << "fiica: parametru int\n\n"; }
18 };
19

4
20 class fiu : public parinte {
21 public:
22 fiu (int a) : parinte (a)
23 { cout << "fiu: parametru int\n\n"; }
24 };
25
26 int main () {
27 fiica Denisa(0);
28 fiu Daniel(0);
29 _getch();
30 return 0;
31 }

Observați diferența între care constructor pentru parinte este apelat atunci când se creează un nou
obiect fiica și care se apelează când se creează un obiect fiu. Diferența este din cauza declarației
constructorului lui fiica și fiu:

1 fiica (int a) // nu s-a specificat nimic: se apeleaza constructorul implicit


2 fiu (int a) : parinte (a) // s-a specificat constructorul: se apeleaza acesta

S-ar putea să vă placă și