poo ierarhii in cpp
DESCRIPTION
oopTRANSCRIPT
![Page 1: POO Ierarhii in Cpp](https://reader035.vdocumente.com/reader035/viewer/2022082204/55cf9736550346d033904a5c/html5/thumbnails/1.jpg)
Derivare, Ierarhii - plan • Relaţia de derivare
– Sintaxa – Tipuri de derivare – Constructori, Destructori – Conversii standard – Copiere – Conflicte – Derivare virtuală
• Polimorfism – suprascriere -> legare statică
• exemplu
– funcţii virtuale -> legare dinamică • exemplu
POO(C++) Gh GRIGORAS 1
![Page 2: POO Ierarhii in Cpp](https://reader035.vdocumente.com/reader035/viewer/2022082204/55cf9736550346d033904a5c/html5/thumbnails/2.jpg)
Ierarhii cpp - Introducere
• C++ a împrumutat de la Simula conceptul de clasă (ca tip utilizator) și cel de ierarhie de clase
• Clasele ar trebui utilizate pentru a modela concepte – atât din domeniul aplicaţiilor cât și din cel al programării
• Un concept nu există izolat, el coexistă cu alte concepte cu care relaţionează
• Automobil – roţi, motor, șoferi, pietoni, camion, ambulanţă, șosea,
ulei, combustibil, parcare, motel, service, etc.
• Exprimarea părţilor comune, a relaţiilor ierarhice dintre clase se realizează prin noţiunea de derivare
POO(C++) Gh GRIGORAS 2
![Page 3: POO Ierarhii in Cpp](https://reader035.vdocumente.com/reader035/viewer/2022082204/55cf9736550346d033904a5c/html5/thumbnails/3.jpg)
struct Angajat{
string nume, prenume;
char initiala;
Data data_angajarii;
short departament;
//…
}
struct Manager{
Angajat ang; // datele managerului
list<Angajat*> grup;//echipa condusa
//…
}
POO(C++) Gh GRIGORAS 3
![Page 4: POO Ierarhii in Cpp](https://reader035.vdocumente.com/reader035/viewer/2022082204/55cf9736550346d033904a5c/html5/thumbnails/4.jpg)
• Un manager este un angajat; compilatorul nu poate înţelege acest lucru din codul scris
• Mai mult, un Manager* nu este un Angajat* deci nu pot pune un Manager într-o listă de Angajaţi decât dacă scriem o conversie explicită
• Soluţia corectă: specificarea(și pentru compilator) că un Manager este un Angajat
struct Manager:public Angajat{
list<Angajat*> grup;//echipa condusa
//…
}
POO(C++) Gh GRIGORAS 4
![Page 5: POO Ierarhii in Cpp](https://reader035.vdocumente.com/reader035/viewer/2022082204/55cf9736550346d033904a5c/html5/thumbnails/5.jpg)
• Se spune că Manager este derivată din Angajat, că Angajat este clasă de bază pentru Manager
• Clasa Manager are ca membri, membrii clasei Angajat și în plus, membrii declaraţi acolo
• Clasa derivată moștenește de la clasa de bază, relaţia se mai numește moștenire.
• Clasa de bază este numită uneori o superclasă iar clasa derivată o subclasă
– Confuzie uneori: clasa derivată este “mai mare” decât clasa de bază în sensul că ea poate conţine date și funcţii în plus
POO(C++) Gh GRIGORAS 5
![Page 6: POO Ierarhii in Cpp](https://reader035.vdocumente.com/reader035/viewer/2022082204/55cf9736550346d033904a5c/html5/thumbnails/6.jpg)
Relaţia de moştenire – Clase derivate
• În C++ : clasă de bază (superclasă), clasă derivată (subclasă)
• Moştenire simplă, moştenire multiplă
POO(C++) Gh GRIGORAS 6
B B1 B2
D D
![Page 7: POO Ierarhii in Cpp](https://reader035.vdocumente.com/reader035/viewer/2022082204/55cf9736550346d033904a5c/html5/thumbnails/7.jpg)
Clase derivate
• Sintaxa:
– Moştenire simplă:
class ClsDer:tip_moşt ClsBaza {};
– Moştenire multiplă:
class ClsDer :tip_moşt ClB1, tip_moşt ClB2,… { };
tip_moşt :: public|protected|private
POO(C++) Gh GRIGORAS 7
![Page 8: POO Ierarhii in Cpp](https://reader035.vdocumente.com/reader035/viewer/2022082204/55cf9736550346d033904a5c/html5/thumbnails/8.jpg)
Clase derivate • Nivele de protecţie(acces) a membrilor unei clase:
– public: cunoscut de oricine
– protected: cunoscut de clasa proprietară, prieteni şi de clasele derivate
– private: cunoscut de clasa proprietară şi de prieteni
• Tipuri de moştenire: – public: membrii public (protected) în bază rămân
la fel în clasa derivată
– protected: membrii public în clasa de bază devin protected în clasa derivată
– private: membrii public şi protected din clasa de bază devin private în clasa derivată; este tipul implicit de moştenire
POO(C++) Gh GRIGORAS 8
![Page 9: POO Ierarhii in Cpp](https://reader035.vdocumente.com/reader035/viewer/2022082204/55cf9736550346d033904a5c/html5/thumbnails/9.jpg)
Clase derivate
• Relaţia friend nu este moştenită, nu este tranzitivă
• În modul de derivare private se poate specifica păstrarea protecţiei unor membri:
class D:private B{
protected: B::p; public: B::q;
//…
};
• Accesul la membri : Funcţiile membru ale unei clase de bază pot fi redefinite în clasa derivată: – Ele pot accesa doar membrii public sau protected
din clasa de bază – Pot accesa funcţiile din clasa de bază folosind operatorul
de rezoluţie ::
POO(C++) Gh GRIGORAS 9
![Page 10: POO Ierarhii in Cpp](https://reader035.vdocumente.com/reader035/viewer/2022082204/55cf9736550346d033904a5c/html5/thumbnails/10.jpg)
Clase derivate
• Constructori, Destructori
– Constructorii şi destructorul nu se moştenesc
– Constructorii clasei derivate apelează constructorii clasei de bază: • Constructorii impliciţi nu trebuie invocaţi
• Constructorii cu parametri sunt invocaţi în lista de iniţializare
• Ordinea de apel: constructor clasă de bază, constructori obiecte membru, constructor clasă derivată
– Obiectele clasei derivate se distrug în ordine inversă: destructor clasă derivată, destructori membri, destructor clasă de bază
POO(C++) Gh GRIGORAS 10
![Page 11: POO Ierarhii in Cpp](https://reader035.vdocumente.com/reader035/viewer/2022082204/55cf9736550346d033904a5c/html5/thumbnails/11.jpg)
class Angajat{
public:
Angajat(const string& n, int d);
//...
private:
string nume, prenume;
short departament;
//..
};
class Manager:public Angajat{
public:
Manager(const string& n, int d, int niv);
//...
private:
list<angajat*> grup;
short nivel;
//...
};
POO(C++) Gh GRIGORAS 11
![Page 12: POO Ierarhii in Cpp](https://reader035.vdocumente.com/reader035/viewer/2022082204/55cf9736550346d033904a5c/html5/thumbnails/12.jpg)
Angajat::Angajat(const string& n, int d)
:nume(n), departament(d)
{
//...
}
Manager::Manager(const string& n, int d, int niv)
:Angajat(n,d), // initializarea bazei
nivel=niv // initializare membri
{
//..
}
• Constructorul clasei derivate poate iniţializa membrii clasei de bază prin invocarea constructorului acesteia în lista de iniţializare
POO(C++) Gh GRIGORAS 12
![Page 13: POO Ierarhii in Cpp](https://reader035.vdocumente.com/reader035/viewer/2022082204/55cf9736550346d033904a5c/html5/thumbnails/13.jpg)
Clase derivate - Conversii standard • Un obiect al clasei derivată poate fi convertit implicit la unul din
clasa de bază – Un Manager poate fi folosit oriunde este acceptabil un Angajat
• O adresă a unui obiect derivat poate fi convertită implicit la o adresă de obiect din clasa de bază – Un Manager& poate fi folosit ca un Angajat&
• Un pointer la un obiect derivat poate fi convertit implicit la un pointer la obiect din clasa de bază – Un Manager* poate fi folosit ca un Angajat*
• Conversia reciprocă poate fi definită cu un constructor în clasa derivată
POO(C++) Gh GRIGORAS 13
![Page 14: POO Ierarhii in Cpp](https://reader035.vdocumente.com/reader035/viewer/2022082204/55cf9736550346d033904a5c/html5/thumbnails/14.jpg)
Clase derivate – Copiere
• Copierea o face constructorul de copiere şi operator=
• În cazul membrilor pointeri aceştia trebuie să existe explicit
• Ordinea de apel a constructorului de copiere:
Clasa de bază Clasa derivată Ordinea de apel
implicit implicit clasa baza, clasa derivată
explicit implicit clasa baza, clasa derivată
implicit explicit constructorul clasei derivate
explicit explicit constructorul clasei derivate trebuie sa apeleze constructorul clasei de bază
POO(C++) Gh GRIGORAS 14
![Page 15: POO Ierarhii in Cpp](https://reader035.vdocumente.com/reader035/viewer/2022082204/55cf9736550346d033904a5c/html5/thumbnails/15.jpg)
Copiere class Angajat{
public:
//...
Angajat&operator=(const Angajat&);
Angajat(const Angajat&);
//...
};
void f(const Manager& m){
Angajat e = m;
// se construieste e din partea Angajat a lui m
e = m;
// se atribuie lui e partea Angajat a lui m
}
• Copierea, atribuirea nu se moștenesc
POO(C++) Gh GRIGORAS 15
![Page 16: POO Ierarhii in Cpp](https://reader035.vdocumente.com/reader035/viewer/2022082204/55cf9736550346d033904a5c/html5/thumbnails/16.jpg)
Ierarhii de clase class Angajat{/*...*/);
class Manager::public Angajat{/*...*/);
class Director::public Manager{/*...*/);
class Secretar::public Angajat{/*...*/);
class AngajatTemporar{/*...*/);
class SecretarTemporar::public AngajatTemporar, public Angajat{/*...*/);
class Consultant::public AngajatTemporar, public Manager{/*...*/);
POO(C++) Gh GRIGORAS 16
AngajatTemporar
SecretarTemporar
Angajat
Secretar Manager
Director Consultant
![Page 17: POO Ierarhii in Cpp](https://reader035.vdocumente.com/reader035/viewer/2022082204/55cf9736550346d033904a5c/html5/thumbnails/17.jpg)
• Utilizarea claselor derivate presupune rezolvarea problemei: dat un pointer la clasa de bază, cărui tip derivat aparţine obiectul pointat?
• Soluţii: 1. Asigurarea ca sunt pointate doar obiecte de un singur tip
2. Folosirea unui câmp tip în clasa de bază
3. Utilizarea operatorului dynamic_cast
4. Utilizarea funcţiilor virtuale
• Pointerii la clase de bază sunt folosiţi la proiectarea containerelor(mulţimi, vectori, liste) – Soluţia 1 conduce la folosirea containerelor omogene (obiecte
de același tip)
– Soluţiile 2-4 permit construirea de containere eterogene
– Soluţia 3 este varianta implementată de sistem a soluţiei 2
– Soluţia 4 este o variantă sigură a soluţiei 2
POO(C++) Gh GRIGORAS 17
![Page 18: POO Ierarhii in Cpp](https://reader035.vdocumente.com/reader035/viewer/2022082204/55cf9736550346d033904a5c/html5/thumbnails/18.jpg)
Câmp tip în clasa de bază struct Angajat{
enum Ang_type{M, A};
Ang_type tip;
string nume, prenume;
char initiala;
Data data_angajarii;
short departament;
//…
}
POO(C++) Gh GRIGORAS 18
struct Manager{
Manager() {tip = M;}
Angajat ang;
list<Angajat*> grup
short nivel;
//…
}
void print_angajat(const Angajat* a){
switch Angajat(a->tip){
case Angajat::A:
cout << a -> nume << ‘\t’ << a->departament << ‘\n’;
//…
break
case Angajat::M:
cout << a -> nume << ‘\t’ << a->departament << ‘\n’;
//…
const Manager* p = static_cast<const Manager*>(a);
cout << “nivel “ << p->nivel<< ‘\n’;
//..
}
![Page 19: POO Ierarhii in Cpp](https://reader035.vdocumente.com/reader035/viewer/2022082204/55cf9736550346d033904a5c/html5/thumbnails/19.jpg)
Câmp tip în clasa de bază
POO(C++) Gh GRIGORAS 19
void print_list(const list<Angajat*>& alist){
for(list<Angajat*>::const_iterator p=alist.begin();
p!=alist.end(); ++p)
print_angajat(*p);
}
• Varianta care ţine cont de partea comună:
void print_angajat(const Angajat* a){
cout << a -> nume << ‘\t’ << a->departament << ‘\n’;
//..
if(a->type == Angajat::M){
const Manager* p = static_cast<const Manager*>(a);
cout << “nivel “ << p->nivel<< ‘\n’;
//..
}
![Page 20: POO Ierarhii in Cpp](https://reader035.vdocumente.com/reader035/viewer/2022082204/55cf9736550346d033904a5c/html5/thumbnails/20.jpg)
Funcţii virtuale class Angajat{
public:
Angajat(const string& n, int d);
virtual void print() const//...
private:
string nume, prenume;
short departament;
//..
};
• Compilatorul va ști să invoce funcţia potrivită atunci când print() este transmisă unui obiect Angajat
• Tipul argumentelor funcţiei virtuale în clasele derivate trebuie să fie aceleași
POO(C++) Gh GRIGORAS 20
![Page 21: POO Ierarhii in Cpp](https://reader035.vdocumente.com/reader035/viewer/2022082204/55cf9736550346d033904a5c/html5/thumbnails/21.jpg)
• O funcţie virtuală trebuie definită pentru clasa în care a fost prima dată declarată (cu excepţia cazului funcţie virtuală pură)
void Angajat::print() const{
cout << nume << ‘\t’ << departament << ‘\n’;
}
class Manager:public Angajat{
public:
Manager(const string& n, int d, int niv);
void print() const; // nu mai e nevoie de cuvantul virtual
//...
private:
list<angajat*> grup;
short nivel;
//...
};
void Manager::print() const{
Angajat::print();
cout << “\tnivel ” << nivel << ‘\n’;
}
POO(C++) Gh GRIGORAS 21
![Page 22: POO Ierarhii in Cpp](https://reader035.vdocumente.com/reader035/viewer/2022082204/55cf9736550346d033904a5c/html5/thumbnails/22.jpg)
Funcţii virtuale • O funcţie din clasa derivată cu același nume și
același set de tipuri de argumente cu o funcţie virtuală din clasa de bază se zice că extinde (override) versiunea din clasa de bază
• Programatorul poate indica versiunea ce trebuie apelată
– Angajat::print();
• Altfel, compilatorul alege versiunea potrivită, în funcţie de obiectul pentru care este invocată
POO(C++) Gh GRIGORAS 22
![Page 23: POO Ierarhii in Cpp](https://reader035.vdocumente.com/reader035/viewer/2022082204/55cf9736550346d033904a5c/html5/thumbnails/23.jpg)
void print_list(const list<Angajat*>& alist){
for(list<Angajat*>::const_iterator p=alist.begin();
p!=alist.end(); ++p)
(*p)->print();
}
int main()
{
Angajat a("Ionescu", 1234);
Manager m("Popescu", 1234, 2);
list<Angajat*> ang;
ang.push_front(&a);
ang.push_front(&m);
print_list(ang);
return 0;
• Rezultatul execuţiei: Popescu 1234
nivel 2
Ionescu 1234
POO(C++) Gh GRIGORAS 23
![Page 24: POO Ierarhii in Cpp](https://reader035.vdocumente.com/reader035/viewer/2022082204/55cf9736550346d033904a5c/html5/thumbnails/24.jpg)
Ierarhia RxR
POO(C++) Gh GRIGORAS 24
PctSpatiu
mutaLa()
transl()
RxRxR
z : float
setZ()
getZ()
RxR
x : float
y : float
setX()
setY() getX()
getY() modul()
PctPlan
transl()
mutaLa()
PlanComplex
phi()
rho()
Complex
conj() operator+()
operator*() operator-()
![Page 25: POO Ierarhii in Cpp](https://reader035.vdocumente.com/reader035/viewer/2022082204/55cf9736550346d033904a5c/html5/thumbnails/25.jpg)
Ierarhia RxR class RxR {
protected:
double x, y;
public:
RxR(double un_x = 0, double un_y = 0) : x(un_x), y(un_y) {}
~RxR() {}
void setX(double un_x) { x = un_x; }
double getX() {return x;}
void setY(double un_y) { y = un_y; }
double getY() { return y; }
double modul();
};
class PctPlan : public RxR {
public:
PctPlan(double un_x=0, double un_y=0) : RxR(un_x, un_y) {}
~PctPlan() {}
void translCu(double, double);
void mutaLa(PctPlan&);
};
POO(C++) Gh GRIGORAS 25
![Page 26: POO Ierarhii in Cpp](https://reader035.vdocumente.com/reader035/viewer/2022082204/55cf9736550346d033904a5c/html5/thumbnails/26.jpg)
Ierarhia RxR class Complex : public RxR {
public:
Complex(double un_x=0, double un_y=0) : RxR(un_x, un_y) {}
Complex conj();
Complex operator+ (Complex&);
};
class RxRxR : public RxR {
protected:
double z;
public:
RxRxR(double un_x, double un_y, double un_z)
: RxR(un_x, un_y), z(un_z) {}
void setZ(double un_z) { z = un_z; }
double getZ() {return z;}
double modul();
};
class PlanComplex : public PctPlan, public Complex {};
POO(C++) Gh GRIGORAS 26
![Page 27: POO Ierarhii in Cpp](https://reader035.vdocumente.com/reader035/viewer/2022082204/55cf9736550346d033904a5c/html5/thumbnails/27.jpg)
POO(C++) 2005-2006 Gh GRIGORAS 27
Clase derivate – Conflicte
• Conflict de metodă: metode cu acelaşi nume în clase incomparabile A, B ce derivează o clasă D
• Conflict de clasă: clasa D derivată din A1 şi A2 iar acestea sunt derivate din B: B este “accesibilă” pe două căi din D
![Page 28: POO Ierarhii in Cpp](https://reader035.vdocumente.com/reader035/viewer/2022082204/55cf9736550346d033904a5c/html5/thumbnails/28.jpg)
POO(C++) 2005-2006 Gh GRIGORAS 28
Clase derivate – Conflicte
• Conflict de clasă: clasa PlanComplex derivată din PctPlan şi Complex iar acestea sunt derivate din RxR
![Page 29: POO Ierarhii in Cpp](https://reader035.vdocumente.com/reader035/viewer/2022082204/55cf9736550346d033904a5c/html5/thumbnails/29.jpg)
POO(C++) 2005-2006 Gh GRIGORAS 29
Ierarhia RxR
class Complex : public RxR {
public:
Complex(double un_x=0, double un_y=0) :
RxR(un_x, un_y) {}
Complex conj();
Complex operator+ (Complex&);
};
class PlanComplex : public PctPlan, public Complex{
public:
PlanComplex(double = 0, double = 0);
~PlanComplex(){};
};
![Page 30: POO Ierarhii in Cpp](https://reader035.vdocumente.com/reader035/viewer/2022082204/55cf9736550346d033904a5c/html5/thumbnails/30.jpg)
POO(C++) 2005-2006 Gh GRIGORAS 30
Ierarhia RxR PlanComplex::PlanComplex(double un_x, double un_y) : PctPlan(un_x, un_y),
Complex(un_x, un_y)
{}
PlanComplex::~PlanComplex()
{
// nimic
}
void main(void) {
PlanComplex pc(5, 5);
cout << pc.modul() << endl;
PlanComplex pc2;
pc2.setX(5);
pc2.setY(5);
cout << pc2.modul() << endl;
}
// 'PlanComplex::modul' is ambiguous
//could be the 'modul' in base 'RxR' of base 'PctPlan' of class 'PlanComplex‘
//or the 'modul' in base 'RxR' of base 'Complex' of class 'PlanComplex'
![Page 31: POO Ierarhii in Cpp](https://reader035.vdocumente.com/reader035/viewer/2022082204/55cf9736550346d033904a5c/html5/thumbnails/31.jpg)
POO(C++) 2005-2006 Gh GRIGORAS 31
Moştenire fără partajare
• Fiecare clasă derivată are câte un exemplar din datele şi metodele clasei de bază
PctPlan::x
PctPlan::y
Complex::x
Complex ::y
PctPlan::modul()
Complex ::modul()
• Soluţia (cazul derivării multiple):
– Clasa de bază virtuală poate fi clasă de bază indirectă de mai multe ori fără a duplica membrii
![Page 32: POO Ierarhii in Cpp](https://reader035.vdocumente.com/reader035/viewer/2022082204/55cf9736550346d033904a5c/html5/thumbnails/32.jpg)
POO(C++) 2005-2006 Gh GRIGORAS 32
Partajare: clase derivate virtuale • Derivare virtuală:
class A1:virtual public B{};
class A2:public virtual B{};
class D: public A1, public A2{};
class PctPlan : virtual public RxR ...
class Complex : virtual public RxR ...
![Page 33: POO Ierarhii in Cpp](https://reader035.vdocumente.com/reader035/viewer/2022082204/55cf9736550346d033904a5c/html5/thumbnails/33.jpg)
POO(C++) 2005-2006 Gh GRIGORAS 33
Clase derivate virtuale • În cazul derivării virtuale, constructorul fiecărei clase derivate este
responsabil de iniţializarea clasei virtuale de bază:
class Baza{ class m1:public D1, public D2{
public: public:
Baza(int){} m1():Baza(2){}
// //
}; };
class D1 : virtual public Baza{ class m2:public D1, public D2{
public: public:
D1():Baza(1){} m2():Baza(3){}
// //
}; };
class D2 : virtual public Baza{
public:
D2():Baza(6){}//…
};
• Un constructor implicit în clasa de bază virtuală, simplifică lucrurile (dar le poate şi complica!)
![Page 34: POO Ierarhii in Cpp](https://reader035.vdocumente.com/reader035/viewer/2022082204/55cf9736550346d033904a5c/html5/thumbnails/34.jpg)
Polimorfism - suprascriere • Legare statică: asocierea apel funcţie --
corp(implementare) funcţie se face înainte de execuţia programului (early binding) – la compilare
POO(C++) 2005-2006 Gh GRIGORAS 34
![Page 35: POO Ierarhii in Cpp](https://reader035.vdocumente.com/reader035/viewer/2022082204/55cf9736550346d033904a5c/html5/thumbnails/35.jpg)
Polimorfism - suprascriere • persoanele, studenţii, profesorii au abilitatea de a semna:
class Persoana {
public:
//…
string getNume() const;
void semneaza();
protected:
string id;
string nume;
};
class Student:public Persoana {
//…
void semneaza();
}
class Profesor:public Persoana {
//…
void semneaza();
}
POO(C++) 2005-2006 Gh GRIGORAS 35
![Page 36: POO Ierarhii in Cpp](https://reader035.vdocumente.com/reader035/viewer/2022082204/55cf9736550346d033904a5c/html5/thumbnails/36.jpg)
Polimorfism - suprascriere
• fiecare semnează in felul său:
void Persoana::semneaza()
{
cout << getNume() << endl;
}
void Student::semneaza()
{
cout << "Student " << getNume() << endl;
}
void Profesor::semneaza()
{
cout << "Profesor " << getNume() << endl;
}
POO(C++) 2005-2006 Gh GRIGORAS 36
![Page 37: POO Ierarhii in Cpp](https://reader035.vdocumente.com/reader035/viewer/2022082204/55cf9736550346d033904a5c/html5/thumbnails/37.jpg)
Polimorfism - suprascriere
• Exemplu: Persoana pers("1001","Popescu Ion");
Student stud("1002", "Angelescu Sorin");
Profesor prof("1003","Marinescu Pavel");
pers.semneaza();
stud.semneaza();
prof.semneaza();
Popescu Ion
Student Angelescu Sorin
Profesor Marinescu Pavel
POO(C++) 2005-2006 Gh GRIGORAS 37
![Page 38: POO Ierarhii in Cpp](https://reader035.vdocumente.com/reader035/viewer/2022082204/55cf9736550346d033904a5c/html5/thumbnails/38.jpg)
Polimorfism - suprascriere
• Exemplu:
// studentul poate semna ca persoana
stud.Persoana::semneaza();
// ... si profesorul poate semna ca persoana
prof.Persoana::semneaza();
Angelescu Sorin
Marinescu Pavel
POO(C++) 2005-2006 Gh GRIGORAS 38
![Page 39: POO Ierarhii in Cpp](https://reader035.vdocumente.com/reader035/viewer/2022082204/55cf9736550346d033904a5c/html5/thumbnails/39.jpg)
Polimorfism - suprascriere
• Suprascriere -> legare statică ( asocierea apel funcţie – implementare se face la compilare):
void semneaza(Persoana& p)
{
p.semneaza();
};
semneaza(pers);
semneaza(stud);// &stud poate inlocui &p
semneaza(prof);// &prof poate inlocui &p
Popescu Ion
Angelescu Sorin
Marinescu Pavel
POO(C++) 2005-2006 Gh GRIGORAS 39
![Page 40: POO Ierarhii in Cpp](https://reader035.vdocumente.com/reader035/viewer/2022082204/55cf9736550346d033904a5c/html5/thumbnails/40.jpg)
Polimorfism - Funcţii virtuale
• Legare dinamică: asocierea apel funcţie -- corp(implementare) funcţie se face la execuţia programului (late binding, run-time binding), pe baza tipului obiectului căruia i se transmite funcţia ca mesaj. În acest caz, funcţia se zice polimorfă
POO(C++) 2005-2006 Gh GRIGORAS 40
![Page 41: POO Ierarhii in Cpp](https://reader035.vdocumente.com/reader035/viewer/2022082204/55cf9736550346d033904a5c/html5/thumbnails/41.jpg)
Implementare polimorfism în C++:
• Declaraţia funcţiei în clasa de bază precedată de cuvântul virtual
class Persoana {
public:
//…
virtual void semneaza();
//…
};
• O funcţie virtuală pentru clasa de bază rămâne virtuală pentru clasele derivate. La redefinirea unei funcţii virtuale în clasa derivată (overriding) nu e nevoie din nou de specificarea virtual
POO(C++) 2005-2006 Gh GRIGORAS 41
![Page 42: POO Ierarhii in Cpp](https://reader035.vdocumente.com/reader035/viewer/2022082204/55cf9736550346d033904a5c/html5/thumbnails/42.jpg)
Polimorfism – funcţii virtuale
• Polimorfism funcţii virtuale-> legare dinamică:
Persoana pers("1001","Popescu Ion");
Student stud("1002", "Angelescu Sorin");
Profesor prof("1003","Marinescu Pavel");
pers.semneaza();
stud.semneaza();
prof.semneaza();
semneaza(pers);
semneaza(stud);
semneaza(prof);
Popescu Ion
Student Angelescu Sorin
Profesor Marinescu Pavel
Popescu Ion
Student Angelescu Sorin
Profesor Marinescu Pavel
POO(C++) 2005-2006 Gh GRIGORAS 42
![Page 43: POO Ierarhii in Cpp](https://reader035.vdocumente.com/reader035/viewer/2022082204/55cf9736550346d033904a5c/html5/thumbnails/43.jpg)
Implementare polimorfism în C++:
• Compilatorul creează o tabelă - VTABLE - pentru fiecare clasă care conţine funcţii virtuale; adresele tuturor funcţiilor virtuale sunt plasate în această tabelă. Sistemul creează un pointer VPTR în fiecare clasă cu funcţii virtuale; el pointează la această tabelă şi alege funcţia corectă la un apel polimorfic
std::cout << sizeof(pers);
• Se obţine: – 32 dacă funcţia semneaza() nu este virtuală – 36 dacă funcţia semneaza() este virtuală
POO(C++) 2005-2006 Gh GRIGORAS 43
![Page 44: POO Ierarhii in Cpp](https://reader035.vdocumente.com/reader035/viewer/2022082204/55cf9736550346d033904a5c/html5/thumbnails/44.jpg)
Implementare polimorfism în C++:
POO(C++) 2005-2006 Gh GRIGORAS 44
![Page 45: POO Ierarhii in Cpp](https://reader035.vdocumente.com/reader035/viewer/2022082204/55cf9736550346d033904a5c/html5/thumbnails/45.jpg)
Implementare polimorfism în C++:
• Orice funcţie membru poate fi declarată virtual, dar:
– constructorii nu pot fi virtual
• Un destructor poate fi virtual; destructorii claselor derivate ar trebui să fie virtuali; asta asigură apelul lor la distrugerea cu delete a pointerilor la clasa de bază
POO(C++) 2005-2006 Gh GRIGORAS 45
![Page 46: POO Ierarhii in Cpp](https://reader035.vdocumente.com/reader035/viewer/2022082204/55cf9736550346d033904a5c/html5/thumbnails/46.jpg)
Destructor virtual
class A{
public:
A(){p = new char[5];}
~A(){delete [] p;}
protected:
char* p;
};
class D:public A{
public:
D(){q = new char[500];}
~D(){delete [] q;}
protected
char* q;
};
void f(){
A* pA;
pA = new D();
//…
delete pA;// doar apel ~A()
}
void main(){
for(int i = 0; i<9; i++)
f();
}
// pentru a se apela si ~D()
// se declara virtual ~A(){…}
POO(C++) 2005-2006 Gh GRIGORAS 46