Sunteți pe pagina 1din 8

Programare orientată pe obiecte Curs 4

PROGRAMARE ORIENTATĂ PE OBIECTE

Moștenirea
Una dintre cele mai importante facilităţi pe care le oferă programarea orientată pe obiecte este
moştenirea claselor. Moştenirea este o formă de reutilizare a codului în care noile clase sunt create
din clase existente prin absorbirea atributelor şi funcțiilor membre, prin înlocuirea/adaugarea unor
funcții membre şi prin adăgarea unor atribute noi.
De regulă, fiecare dată sau funcţie membru a clasei de bază se moşteneşte în clasa derivată,
diferind doar protecţia acestora.

Important: Nu se moştenesc constructorii şi destructorii, supraîncărcarea operatorului =, acestea


fiind metode specifice clasei.

Exemplu: Dacă am construit clasa Patrulater putem construi, pornind de la aceasta, clasele
Dreptunghi și Romb, apoi putem construi clasa Patrat care să aibă la bază atât clasa Dreptunghi cât
și clasa Romb. Clasa Patrulater se va numi clasă de bază pentru clasele Romb și Dreptunghi iar
acestea (clasele Romb și Dreptunghi) se numesc clase derivate. La rândul lor, clasele Romb și
Dreptunghi sunt clase de bază pentru clasa Patrat în vreme ce clasa Pătrat este clasă derivată din
clasele Romb și Dreptunghi.

Important: Moştenirea conduce la structuri ierarhice arborescente.

Patrulater

Dreptunghi Romb

Patrat
Sintaxă
class IdClasaDerivata: modif_acces1 IdClasaBaza1, …,
modif_accesN IdClasaBazaN{
//date si metode specifice clasei derivate
};
unde:
 IdClasaDerivata este numele clasei derivate
 IdClasaB1, …, dClasaBazaN sunt clasele de bază de la care se moştenesc datele
şi metodele
 modif_acces1, …, modif_accesN sunt modificatori de acces: public, protected,
private

1
Programare orientată pe obiecte Curs 4

Protectia în clasa de bază Modificator de acces utilizat Drept de acces în clasa


în lista claselor de bază derivată
public public public
private public inaccesibil
protected public protected
public private private
private private inaccesibil
protected private private
public protected protected
private protected inaccesibil
protected protected protected

Exemplu
class Persoana{
protected:
char nume[100];
char cnp[13];
public:
Persoana(char* nume,char cnp[13]);
char* getNume();
char* getCnp();
};
class Student: public Persoana{
protected:
int an;
int punctaj;
public:
Student(char* nume,char cnp[13],int punctaj,int an);
int getPunctaj();
int getAn();
};

class Produs{
protected:
char nume[100];
float pret;
public:
Produs(char *nume, float pret);
char* getNume();
float getPret();
void afisare();
};
class ProdusAlimentar: public Produs{
protected:
int valabilitate;
public:
ProdusAlimentar(char *nume, float pret, int valabilitate);
int getValabilitate();
void afisare();
};

2
Programare orientată pe obiecte Curs 4

class ProdusNealimentar: private Produs{


protected:
int garantie;
public:
ProdusNealimentar(char *nume, float pret, int garantie);
int getGarantie();
void afisare();
};
...
int main(){
ProdusAlimentar prodA("Paine",2,5);
prodA.afisare();
ProdusNealimentar prodN("TV LED",2000,24);
prodN.afisare();//eroare
}

Tipuri de Moştenire
 Moştenire simplă – clasa derivată preia caracteristicile şi metodele unei singure clase
de bază
 Moştenire multiplă - clasa derivată preia caracteristicile şi metodele de la mai multe
clase de bază

Exemplu

class Automobil{
protected:
char* marca;
char* model;
int pret;
public:
static const int nrAxe=2;
static char* tipAutovehicul(){
return "Automobil";
}
Automobil(char* marca,char* model,int pret);
Automobil(const Automobil&);
~Automobil();
void scrieInformatii(ostream& out);
static Automobil* citesteDate();
};

class AutomobilArdereInterna: public Automobil{


protected:
int putere;
int cc;
char* combustibil;
double consum;
public:
AutomobilArdereInterna(char* marca,char* model,int putere,int pret,int
cc,char* combustibil,double consum);
~AutomobilArdereInterna();
void scrieInformatii(ostream& out);
static Automobil* citesteDate();
};

3
Programare orientată pe obiecte Curs 4

class AutomobilElectric: public Automobil{


protected:
int putere;
char* baterie;
int autonomie;
public:
AutomobilElectric(char* marca,char* model,int putere,int pret,char*
baterie,int autonomie);
~AutomobilElectric();
void scrieInformatii(ostream& out);
static Automobil* citesteDate();
};

//vom declara mai tarziu clasa Automobil Hibrid


class AutomobilHibrid:public AutomobilArdereInterna,public AutomobilElectric{
...
};

Utilizarea constructorilor în procesul de moştenire


 Dacă o clasă A este derivata din clasele B1, …, Bn atunci constructorul clasei A trebuie să
aibă suficienţi parametri pentru a iniţializa datele membru ale claselor B1,…, Bn.
 La crearea unui obiect al clasei A se vor apela mai întâi constructorii claselor B1, …,Bn, în
ordinea specificată în lista de moştenire, pentru a se iniţializa datele membre ale claselor de
bază şi apoi se vor executa intrucţiunile constructorului clasei A.
 dacă constructorul clasei derivate nu apelează explicit constructorul uneia din clasele de
bază atunci compilatorul va apela automat constructorul implicit al acelei clase de bază
 Dacă clasa derivată nu are definit un constructor de copiere atunci compilatorul
generează unul automat care va realiza copierea datelor membre moştenite apelând la
constructorii de copiere ai claselor de bază (definiţi de utilizator sau generaţi de
compilator), iar datele specifice clasei derivate se vor copia bit cu bit.
 Dacă clasa derivată are definit un constructor de copiere atunci acesta va realiza
copierea tuturor datelor membre (moştenite sau proprii) - apelând eventual la constructorii
claselor de bază

Sintaxă
class A: public B1, …, public Bn{

A(lista parametri);//constructor

};

A::A(lista parametri): B1(sub_lista_param1,…,Bn(sub_lista_paramn){


instructiuni
}

4
Programare orientată pe obiecte Curs 4

Exemplu
Automobil::Automobil(char* marca,char* model,int pret){
this->marca=new char[strlen(marca)+1];
strcpy(this->marca,marca);
this->model=new char[strlen(model)+1];
strcpy(this->model,model);
this->pret=pret;
}
AutomobilArdereInterna::AutomobilArdereInterna(char* marca,char* model,int
putere,int pret,int cc,char* combustibil,double consum):
Automobil(marca,model,pret){
this->putere=putere;
this->cc=cc;
this->combustibil=new char[strlen(combustibil)+1];
strcpy(this->combustibil,combustibil);
this->consum=consum;
}
AutomobilElectric::AutomobilElectric(char* marca,char* model,int putere,int
pret,char* baterie,int autonomie):
Automobil(marca,model,pret){
this->putere=putere;
this->baterie=new char[strlen(baterie)+1];
strcpy(this->baterie,baterie);
this->autonomie=autonomie;
}

Utilizarea destructorilor în procesul de moştenire


 La distrugerea unui obiect al clasei derivate compilatorul va executa mai întâi destructorul
clasei derivate şi apoi destructorii claselor de bază, în ordinea inversă apelului constructorilor

Exemplu
Automobil::~Automobil(){
delete marca;
delete model;
}
AutomobilArdereInterna::~AutomobilArdereInterna(){
delete combustibil;
}
AutomobilElectric::~AutomobilElectric(){
delete baterie;
}

Exemplu
class Imprimanta{
protected:
int rezolutie;
public:
Imprimanta(int rezolutie=600){
this->rezolutie = rezolutie;
cout<<"Apel Constr. Imprimanta\n";
}
~Imprimanta(){

5
Programare orientată pe obiecte Curs 4

cout<<"Apel Destr. Imprimanta\n";


}
void print(char *text){
cout<<"Print "<<text<<"\n";
}
};

class Scaner{
protected:
int rezolutie;
public:
Scaner(int rezolutie=1200){
this->rezolutie = rezolutie;
cout<<"Apel Constr. Scaner\n";
}
~Scaner(){
cout<<"Apel Destr. Scaner\n";
}
void scan(){
cout<<"Scanez\n";
}
};

class MultiFunctionala: public Imprimanta, public Scaner{


public:
MultiFunctionala(int rezI, int rezS):
Imprimanta(rezI), Scaner(rezS){
cout<<"Apel Constr. MultiFunctionala\n";
}
~MultiFunctionala(){
cout<<"Apel Destr. MultiFunctionala\n";
}
};
void main(){
MultiFunctionala m(300,600);
m.print("hello");
m.scan();
}

În urma execuției se va afișa:


Apel Constr. Imprimanta
Apel Constr. Scaner
Apel Constr. MultiFunctionala
Imprimare: hello
Scanare:
Apel Destr. MultiFunctionala
Apel Destr. Scaner
Apel Destr. Imprimanta
Press any key to continue . . .

Cast între pointerii la clasa de bază şi pointerii la clasa derivată


Un obiect al unei clase derivate public poate fi tratat ca obiect al clasei ei de bază. Pe de altă parte,
programatorul trebuie să folosească un cast explicit pentru a converti un pointer la clasa de bază
6
Programare orientată pe obiecte Curs 4

într-un pointer la o clasă derivata deoarece compilatorul consideră că această operaţie este una
periculoasă. Acest proces se numeşte downcasting a pointer. Un astfel de cast trebuie făcut cu grijă
de către programator, asigurându-se că tipul pointerului se potriveşte cu tipul obiectului către care
pointează.
Prin upcasting a pointer înțelegem operația inversă, prin care un pointer al clasei derivate este
convertit la un pointer al clasei de bază.
Există și metode mai elaborate pentru acest tip de conversie, prin run-time type identification
(RTTI), folosind dynamic_cast.
Operatorul dynamic_cast se foloseşte pentru implementarea conversiilor care au loc în timpul
rulării programului şi pe care compilatorul nu le poate verifica. Acest operator este folosit, de
regulă, pentru downcasting de la un pointer la clasa de bază către un pointer la clasa derivată. El
poate fi folosit doar pentru pointeri sau referinţe la obiecte.

Important: Operatorul dynamic_cast poate fi folosit doar cu clase în care cel puțin o funcție este
virtuală (polymorphic class). Acest operator va fi prezentat cursul următor, împreuna cu
polimorfismul.

void main(){
Automobil a1("Honda","Civic",20000);
Automobil a2(a1);//constructor de copiere
AutomobilArdereInterna aai=AutomobilArdereInterna("BMW","Serie 3", 180,
30000,1998,"benzina",5.2);
AutomobilElectric ae=AutomobilElectric("Mitsubishi","i-MiEV", 60,35000,
"Litiu – Ion 330V/16 kWh",60);

cout<<"1."<<endl;
Automobil a=aai;//conversie implicitaimplicit
a.scrieInformatii(cout);
aai.scrieInformatii(cout);

cout<<"2."<<endl;
AutomobilArdereInterna *paai;
Automobil *pa=&aai;//corect
(*pa).scrieInformatii(cout);

cout<<"3."<<endl;
//paai=pa;//eroare !!!!
paai=static_cast<AutomobilArdereInterna*>(pa);
paai->scrieInformatii(cout);

cout<<"4."<<endl;
pa=&a2;
//paai=pa;//eroare !!!!
paai=static_cast<AutomobilArdereInterna*>(pa);//Corect, dar probleme la
preluare date !!!!!!!!!!!!
paai->scrieInformatii(cout);

cout<<"5."<<endl;
pa=&ae;
//paai=pa;//eroare !!!!
paai=static_cast<AutomobilArdereInterna*>(pa);//Conversia se va realiza,
dar apare eroare la afisare !!!!!!!!!!!!
//paai->scrieInformatii(cout);

//paai=dynamic_cast<AutomobilArdereInterna*>(&ae);//Eroare - necesita
clase cu functii virtuale
7
Programare orientată pe obiecte Curs 4

În urma execuției se va afișa:

1.
Automobil
Marca: BMW
Marca: Serie 3
Pret: 30000 EUR
======================================
Automobil ardere interna
Marca: BMW
Marca: Serie 3
Capacitate cilindrica: 1998 cc.
Tip combustibil: benzina
Putere: 180 cp.
Consum: 5.2 litri/100 km.
Pret: 30000 EUR
======================================
2.
Automobil
Marca: BMW
Marca: Serie 3
Pret: 30000 EUR
======================================
3.
Automobil ardere interna
Marca: BMW
Marca: Serie 3
Capacitate cilindrica: 1998 cc.
Tip combustibil: benzina
Putere: 180 cp.
Consum: 5.2 litri/100 km.
Pret: 30000 EUR
======================================
4.
Automobil ardere interna
Marca: Honda
Marca: Civic
Capacitate cilindrica: -858993460 cc.
Tip combustibil: Honda
Putere: -858993460 cp.
Consum: 4.24399e-310 litri/100 km.
Pret: 20000 EUR
======================================
5.
Press any key to continue . . .

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