Sunteți pe pagina 1din 8

MOSTENIREA OOP ofera posibilitatea refolosirii intr-un program a unei clase pe care am mai utilizat-o intr-un alt program,

economisind astfel timp si efort de programare. Sunt situatii in care o clasa foloseste caracteristici ale unei clase existente, adaugand unul sau mai multe date membre sau functii membre. In acest caz, C++ ofera posibilitatea de a crea noul obiect pe baza caracteristicilor obiectului existent. Atunci cand o noua clasa este creata pe baza uneia deja existente, noua clasa este o clasa derivata. Definitie: Prin mostenire se intelege acea proprietate a claselor prin care o clasa nou construita poate prelua datele si metodele unei clase mai vechi. Clasei noi i se pot adauga date si metode. Acest mecanism mai este cunoscut sub numele de derivare a claselor. Avantajul acestui procedeu este ca se poate prelua soft gata facut, care se dezvolta. Persoana care dezvolta softul nu trebuie sa cunoasca detaliile de implementare ale acestuia, ci doar documentatia de utilizare. Daca avem clasele X1, X2,Xn, putem construi clasa Xn+1 care are, pe langa datele si metodele celor n clase enumerate, propriile date si metode. Clasele X1, X2,Xn se numesc clase de baza, iar clasa Xn+1 clasa derivata. Declaratia unei clase derivate:
class NumeClasaDerivata : modificator_acces NumeClasaDeBaza { //date si metode specifice clasei derivate }

Obiectele din clasa derivata vor avea acces atat la membrii din clasa de baza cat si la membrii din clasa derivata. Atentie daca si in clasa de baza si in clasa derivata doi membri (camp de data sau metoda) se numesc la fel, in clasa derivata daca se va dori sa se faca referire la membrul din clasa de baza se va folosi operatorul de rezolutie precedat de numele clasei de baza, altfel referirea va fi in mod implicit la membrul din clasa curenta (clasa derivata).

class C1 {public: tip1 camp1; metoda1(); .. }; class C2: public C1 {public: tip1 camp1; metoda1(); . };

//clasa de baza

//clasa derivata

void main() {C2 ob; ob.camp1; ob.C1::camp1; ob.metoda1(); ob.C1::metoda1(); }

//acceseaza campul din clasa C2 //acceseaza campul din clasa C1 //acceseaza metoda din clasa C2 //acceseaza metoda din clasa C1

Exemplu: Fie clasa Persoana ce are ca date membre numele, prenumele si anul nasterii unei persoane. Vrem sa cream clasa Student care are, pe langa datele persoanei, si facultatea, specializarea si anul la care studiaza. Derivam clasa Student din clasa Persoana. #include<iostream.h> #include<conio.h> /*****************************************/ class persoana //clasa de baza {public: char nume[20], prenume[20]; int an; void afisare() {cout<<endl<<"datele persoanei "<<endl; cout<<nume<<" "<<prenume<<endl; cout<<"Are "<<2005-an<<" ani"<<endl; } void citire() { cout<<"numele "; cin>>nume; cout<<"prenumele "; cin>>prenume; } };

/**************************************************************/ class student: public persoana //clasa derivata {public: char fact[20],spec[20]; int an; void citire() {cout<<"facultatea "; cin>>fact; cout<<"specializarea "; cin>>spec; } void afisare()

{cout<<endl<<"datele studentului "<<endl; cout<<"facultatea "<<fact<<endl; cout<<"specializarea "<<spec<<endl; cout<<"anul "<<an<<endl;} }; void main() {clrscr(); persoana p1; p1.citire(); cout<<"anul nasterii "; cin>>p1.an; p1.afisare(); student s1; cout<<endl<<"citire date student: "; s1.persoana::citire(); cout<<"anul nasterii "; cin>>s1.persoana::an; s1.citire(); cout<<"in ce an este studentul? "; cin>>s1.an; cout<<"datele din ambele clase "<<endl; s1.persoana::afisare(); s1.afisare(); getch(); } Observatie: Atunci cand se deriveaza o clasa din alta clasa, membrii privati ai clasei de baza sunt accesibili clasei derivate prin intermediul metodelor publice oferite de clasa de baza. Din aceasta cauza, o clasa derivata nu poate accesa direct un membru privat al clasei de baza prin utilizarea operatorului punct. In ceea ce priveste folosirea (compilarea si editarea de legaturi) clasei derivate in sensul programarii, clasa de baza si cea derivata pot apare in acelati fisier sursa, sau pot fi declarate in fisiere diferite.

Probleme propuse: 1. Sa se defineasca clasa complex ca si clasa de baza apoi o clasa vector care sa mosteneasca clasa complex si care sa permita prelucrarea unui sir de numere complexe. Cerinte: -se citesc n numere complexe -sa se afiseze numerele in format complex -sa se determine suma acelor n numere complexe -sa se determine suma a doi vectori de numere complexe Schimbarea domeniilor de acces prin derivare Indiferent de tipul derivarii, functiile membre ale clasei derivate nu au acces in zona private a clasei de baza.

Prin derivare public, membrii publici si protected ai clasei de baza isi pastreaza caracterul de public, respectiv protected (derivarea publica, extinde domeniile public si protected si pentru membrii derivatei) Prin derivare protected, membrii public si protected ai clasei de baza devin protected pentru clasa derivata Prin derivare private, membrii public si protected ai clasei de baza devin membri private in clasa derivata Daca nu se specifica tipul accesului mostenit prin derivare, se considera implicit private.

Modificator acces la membrii clasei de baza private public protected

Accesul in clasa derivata (noul acces) dobandit prin mostenire publica private public protected

Accesul in clasa derivata (noul acces) dobandit prin mostenire protejata private protected protected

Accesul in clasa derivata (noul acces) dobandit prin mostenire privata private private private

Observatie: Prin derivarea private, se opreste posibilitatea de a transmite catre un urmas dreptul de acces la clasa de baza, in cazul mai multor niveluri de derivare ierarhica. Pentru primul nivel de derivare, zonele public si protected sunt totusi accesibile. Prin derivarea protected, membrii public si protected ai clasei derivate pot fi transmisi mai departe si altor clase, prin derivare succesiva. Constructorii claselor derivate Constructorii si destructorii sunt functii membre care nu se mostenesc. La instantierea unui obiect din clasa derivata se apeleaza mai intai constructorii claselor de baza, in ordinea in care acestia apar in lista din declararea clasei derivate. La distrugerea obiectelor, se apeleaza intai destructorul clasei derivate, apoi destructorii claselor de baza. Transmiterea argumentelor unei functii constructor din clasa de baza se face folosind o forma extinsa a declaratiei constructorului clasei derivate, care transmite argumentele unui sau mai multor constructori din clasa de baza. In general, clasele utilizeaza constructori definiti de programator. In cazul in care acestia lipsesc, compilatorul genereaza automat un constructor implicit pentru clasa respectiva. Acelasi lucru se intampla si in cazul constructorilor de copiere. La instantierea unui obiect din clasa derivata, o parte din valorile primite ca parametri folosesc la initializarea datelor membru ale claselor de baza, iar restul initializeaza datele membru specifice clasei derivate.

Fie clasa de baza B si D o clasa derivata a ei. Noua clasa D isi are proprii ei constructori, impliciti si/sau expliciti. Constructorii clasei D sunt responsabili si cu initializarea corecta a datelor mostenite. In mod normal, el apeleaza la constructorul lui B, chiar daca noi nu cerem acest lucru, dupa care completeaza clasa cu datele si functiile specifice clasei D. In cazul destructorului, lucrurile stau similar, numai ca ele se deruleaza in ordine inversa. La crearea unui obiect derivat, ordinea de executie este: - constructor de baza - constructor derivat iar la eliberarea memoriei:

destructor derivat destructor de baza

Exemplu: Fie clasa Angajat care mosteneste clasa Persoana. Observati definirea constructorului clasei derivate!!!
class Persoana { char nume[20]; int varsta; long tel; public: Persoana(char c[20],int v,long t) {strcpy(nume,c); varsta=v; tel=t;} void afis() {cout<<nume<<" "<<varsta<<" "<<tel<<endl;} ~Persoana() {cout<<"am apelat destructorul clasei Persoana"<<endl;} }; class Angajat : public Persoana { public: char functia[15]; long sal; int vechime; Angajat(char c[20],int v,long t,char f[15],long vech):Persoana(c,v,t) {strcpy(functia,f); sal=s; vechime=vech;} void afis_angajat() {afis(); cout<<functia<<" "<<vechime<<" "<<sal<<endl;} ~Angajat() {cout<<"am apelat destructorul clasei Angajat"<<endl;} }; void main() {Persoana p1("Popescu",30,422078); p1.afis(); Angajat a1("Ionescu B.",33,319968,"profesor",4000000,9); a1.afis_angajat(); }

s,int

La distrugerea obiectelor, se va afisa:


am apelat destructorul clasei Persoana pentru p1 am apelat destructorul clasei Persoana pentru a1 am apelat destructorul clasei Angajat pentru a1

Daca clasa derivata nu are constructori expliciti, valorile sunt cele puse de constructorul din clasa de baza. Exista un constructor de copiere implicit, care sta la baza conversiilor unui Angajat intr-o Persoana. Mostenirea multipla

O clasa poate sa mosteneasca mai multe clase de baza, ceea ce inseamna ca toti membrii claselor de baza vor fi mosteniti de clasa derivata. In aceasta situatie apare mecanismul mostenirii multiple.

Exercitiu: Se implementeaza ierahia de clase din figura.


#include <iostream.h> class baza1 { protected: int x; public: baza1 (int xx) {x=xx;cout<<"Constructor cls. baza1\n"; cout<<x<<'\n';} ~baza1() {cout<<"Destructor baza1\n"<<x<<'\n';} void aratax() {cout<<"x="<<x<<'\n';} }; class baza2 { protected: int y; public: baza2 (int yy) {y=yy; cout<<"Constructor baza2\n"<<y<<'\n';} ~baza2() {cout<<"Destructor baza2\n";} void aratay(){cout<<"y="<<y<<'\n';} }; class derivat: public baza1, public baza2 { public: derivat(int xx, int yy):baza1(xx), baza2(yy) {cout<<"Constructor derivat\n"; cout<<x<<' '<<y<<'\n';} ~derivat() {cout<<"Destructor derivat\n"; cout<<x<<' '<<y<<'\n';} int arata(){cout<<x<<' '<<y<<'\n';} void seteaza(int xx, int yy){x=xx; y=yy;} }; void main() { derivat obiect(7,8);/*Constructor cls. baza1 7 8 Constructor derivat 7 obiect.arata(); // 7 8 obiect.seteaza(1,2); obiect.aratax(); // x=1 obiect.aratay(); // y=2 obiect.arata(); // 1 2

Constructor baza2 */

baza1 }

/* Destructor derivat 1 2 1 */

Destructor baza2 2

Destructor

Asa cum ilustreaza exemplul, la declararea obiectului obiect de tipul derivat s-au apelat constructorii claselor de baza (baza1 si baza2), in ordinea in care apar in declararea clasei derivate: mai intai constructorul clasei baza1, in care x este data membru protejata (accesibila din clasa derivat); apoi constructorul clasei baza2 , in care y este data membru protejata (accesibila din clasa derivat); apoi constructorul clasei derivat care le incorporeaza pe acestea intr-un singur obiect. Clasa derivat nu are date membre, ci doar metode.

Dupa iesirea din blocul in care a fost declarata variabila obiect, se apeleaza automat destructorii, in ordine inversa apelarii constructorilor.

Exercitii:

1.