Documente Academic
Documente Profesional
Documente Cultură
CUPRINS
Motenire Clase derivate Modificatori de acces
Constructori i destructori
Supradefinirea operatoriilor Supradefinirea funciilor Funcii virtuale Destructori virtuali Polimorfism
MOTENIRE (INHERITANCE)
Definiie Motenirea este un mecanism care permite unei clase A s moteneasc atribute i metode ale unei clase B. n acest caz obiectele clasei A au acces la membrii clasei B fr a fi nevoie s le redefinim
Terminologie
Clas de baz
Clasa care este motenit
Clas derivat
O clas specializat a clasei de baz
EXEMPLU
Poligon
Dreptunghi
Triunghi
Dreptunghi
Triunghi
Multipl
unde
modificatorDeAcces specific tipul derivrii private (valoare implicit) protected public
MODIFICATORI DE ACCESS
Funciile membre ale clasei derivate au acces la membrii publici i protected ai clasei de baz Pentru a controla accesul la membrii clasei de baz sunt folosii specificatorii de acces
Clasa de Baz private protected public private protected public private protected public Modificatorul de acces private private private protected protected protected public public public Ce se poate accesa in clasa derivat nu este accesibil private private nu este accesibil protected protected nu este accesibil protected public Ce se poate accesa n exterior nu este accesibil nu este accesibil nu este accesibil nu este accesibil nu este accesibil nu este accesibil nu este accesibil nu este accesibil public
MODIFICATORI DE ACCES
class B{ public: int a; protected: int b; private: int c; }; class D1: B{ /*derivare private*/ void foo(){ int _a=a; //Ok int _b=b; //Ok int _c=c; //eroare: B::c este privat } }; class D2: protected B{ void foo(){ int _a=a; //Ok int _b=b; //Ok int _c=c; //eroare: B::c este privat } }; class D3: public B{ void foo(){ int _a=a; //?? int _b=b; //?? int _c=c; //?? } }; class DD : D1 { void foo(); }; void DD::foo() { a = 10; // ?? b = 20; // ?? c = 30; // ?? } int main(int argc, char** argv) { D1 d1; D2 d2; D3 d3; int v1=d1.a; //eroare: B::a nu este accesibil int v2=d1.b; //eroare: B::b este protected int v3=d1.c; //eroare: B::c nu este accesibil int v4=d2.a; //eroare: B::a nu este accesibil int v5=d2.b; //eroare: B::b este protected int v6=d2.c; //eroare: B::c este privat int v7=d3.a; //OK int v8=d3.b; //eroare: B::b este protected int v9=d3.c; //eroare: B::c este privat return 0; }
CE SE MOTENETE?
n pricipiu, fiecare membru al clasei de baz este motenit de clasa derivat Doar cu diferite permisiuni de acces Dar, exist cteva excepii Constructorii Destructorii
Operatorul =
Funciile friend
10
CONSTRUCTORII I DESTRUCTORII
Constructori Prima dat se apeleaz constructorul clasei de baz i apoi constructorul clasei derivate Destructori Sunt apelai n ordine invers fa de constructori, mai nti se apeleaz destructorul clasei derivate apoi cel al clasei de baz
11
CONSTRUCTORII I DESTRUCTORII
class Ferma { protected: char* nume; public: Ferma(){ cout << "Ferma: Default constructor " << this <<endl; } Ferma(char* nume){ cout << "Ferma: Full constructor " << this <<endl; . } ~Ferma(){ cout << "Ferma: Destructor " << this <<endl; } }; class FermaAgricola : public Ferma{ protected: int suprafata; public: FermaAgricola(){ cout << "FermaAgricola: Default constructor << this <<endl; } FermaAgricola(char* nume, int suprafata){ cout << "FermaAgricola: Full constructor<< this <<endl;; . } ~FermaAgricola(){ cout << "FermaAgricola: Destructor " << this <<endl; } };
Rezultat Ferma: Default constructor 0x28ff18 FermaAgricola: Default constructor 0x28ff18 FermaAgricola: Destructor 0x28ff18 Ferma: Destructor 0x28ff18
12
Ferma: Default constructor 0x28ff18 FermaAgricola: Full constructor 0x28ff18 FermaAgricola: Destructor 0x28ff18 Ferma: Destructor 0x28ff18
CONSTRUCTORII I DESTRUCTORII
class Ferma { protected: char* nume; public: Ferma(){ cout << "Ferma: Default constructor " << this <<endl; } Ferma(char* nume){ cout << "Ferma: Full constructor " << this <<endl; . } ~Ferma(){ cout << "Ferma: Destructor " << this <<endl; } }; class FermaAgricola : public Ferma{ protected: int suprafata; public: FermaAgricola(){ cout << "FermaAgricola: Default constructor << this <<endl; } FermaAgricola(char* nume, int suprafata){ cout << "FermaAgricola: Full constructor<< this <<endl;; . } ~FermaAgricola(){ cout << "FermaAgricola: Destructor " << this <<endl; } };
Rezultat Ferma: Default constructor 0x28ff18 FermaAgricola: Default constructor 0x28ff18 FermaAgricola: Destructor 0x28ff18 Ferma: Destructor 0x28ff18
13
Ferma: Default constructor 0x28ff18 FermaAgricola: Full constructor 0x28ff18 FermaAgricola: Destructor 0x28ff18 Ferma: Destructor 0x28ff18
CONSTRUCTORII I DESTRUCTORII
class Ferma { protected: char* nume; public: Ferma(){ cout << "Ferma: Default constructor " << this <<endl; } Ferma(char* nume){ cout << "Ferma: Full constructor " << this <<endl; . } ~Ferma(){ cout << "Ferma: Destructor " << this <<endl; } }; class FermaAgricola : public Ferma{ protected: int suprafata; public: FermaAgricola(){ cout << "FermaAgricola: Default constructor << this <<endl; } FermaAgricola(char* nume, int suprafata) : Ferma(nume) { cout << "FermaAgricola: Full constructor<< this <<endl;; . } ~FermaAgricola(){ cout << "FermaAgricola: Destructor " << this <<endl; } };
Rezultat Ferma: Default constructor 0x28ff18 FermaAgricola: Default constructor 0x28ff18 FermaAgricola: Destructor 0x28ff18 Ferma: Destructor 0x28ff18
14
Ferma: Full constructor 0x28ff18 FermaAgricola: Full constructor 0x28ff18 FermaAgricola: Destructor 0x28ff18 Ferma: Destructor 0x28ff18
CONSTRUCTORUL DE COPIERE
Clasa derivat nu are definit un contructor de copiere => se apeleaz constructorul de copiere creat de compilator Clasa derivat are definit un contructor de copiere => se apeleaz constructorul de copiere definit (ex. FermaAnimale a(Ferma 1, 20), copie(a);)
Cum se poate modifica codul astfel nct s se realizeze i o copie a atributelor clasei de baz?
FermaAgricola(const FermaAgricola& f){ cout << "FermaAgricola: Copy constructor " << this <<endl; } Ferma: Default constructor 0x28ff10 FermaAgricola: Copy constructor 0x28ff10 FermaAgricola: Destructor 0x28ff10 Ferma: Destructor 0x28ff10
15
CONSTRUCTORUL DE COPIERE
Apelarea constructorului supraclasei
FermaAgricola(const FermaAgricola& f) : Ferma(f.nume){ cout << "FermaAgricola: Copy constructor " << this <<endl; this->suprafata = f.suprafata; } Ferma: Full constructor 0x28ff10 FermaAgricola: Copy constructor 0x28ff10 FermaAgricola: Destructor 0x28ff10 Ferma: Destructor 0x28ff10
FermaAgricola(const FermaAgricola& f) : Ferma(f){ cout << "FermaAgricola: Copy constructor " << this <<endl; this->suprafata = f.suprafata; }
Ferma: Copy constructor 0x28ff10 FermaAgricola: Copy constructor 0x28ff10 FermaAgricola: Destructor 0x28ff10 Ferma: Destructor 0x28ff10
16
SUPRADEFINIREA OPERATORILOR
Funciile operator membre ale clasei de baz sunt motenite de clasele derivate i pot fi redefinite n clasele derivate EXCEPIE Operatorul =()
Dac este definit n clasa derivat, el este apelat, dar nu se mai apeleaz cel din clasa de baz Dac nu este definit n clasa derivat, se apeleaz implicit copierea pentru atributele clasei derivate i operatorul =() definit n clasa de baz
17
CONVERSII DE TIP
Permise Nepermise
D B *D *B *B (B*)*D
FermaAgricola fa("fermaAgr", 30), *pfa; Ferma f("ferma2"), *pf; FermaAgricola fa2(fa); fa2.setSuprafata(100);
B D *B *D
Output
cout << "Conversie implicita FermaAgricola -> Ferma\n"; f = fa; cout << f << endl; cout << "Conversie implicita FermaAgricola -> *Ferma\n"; pf = &fa2; cout << *pf << endl; cout << "Conversie explicita *Ferma -> *FermaAgricola\n"; pfa = (FermaAgricola*)pf; cout << *pfa << endl;
fermaAgr
fermaAgr
18
fermaAgr 770887
Ferma agricola: 'fermaAgr cu suprafata 30' isi schimba numele in 'Ferma ABC 2'
19
Ferma agricola: 'fermaAgr cu suprafata 30' isi schimba numele in 'Ferma ABC 2'
20
FUNCII VIRTUALE
void Ferma::afisare() { cout << "Ferma: "<< nume << endl; }
void FermaAgricola::afisare() { cout << "Ferma Agricola: " << nume <<" cu suprafata " << suprafata << endl; }
int main() { Ferma *ff; FermaAgricola ffa("Ferma Buzias", 300); ff = &ffa; ff->afisare(); return 0; }
Care este varianta de afiare dorit? Output Varianta A Ferma: Ferma Buzias
Ce se va afia?
21
FUNCII VIRTUALE
Soluia Adugarea unui cmp care specific tipul obiectului Funcii viruale
Tipuri de legturi
Static (early binding)
Versiunea funciei apelate se stabilete n momentul compilrii
22
FUNCII VIRTUALE
Sintax
virual prototipFuncie;
Caracteristici Atributul virtual este motenit Este un tip special de funcie care determin tipul derivat corespunztor pentru o funcie cu acelasi prototip Specificarea cuvntului virtual n faa funciei Sunt funcii membre nestatice Redefinirea i redeclararea funciilor virtuale n clasele derivate nu este obligatorie Constructori nu pot fi funcii virtuale Redefinirea sau schimbarea prototipului este acceptabil doar dac se modific valoarea de return
23
FUNCII VIRTUALE
class Ferma{ ..... virtual void afisare() { cout << "Ferma: "<< nume << endl; } }; void FermaAgricola::afisare() { cout << "Ferma Agricola: " << nume <<" cu suprafata " << suprafata << endl; } int main() { Ferma *ff; FermaAgricola ffa("Ferma Buzias", 300); ff = &ffa; ff->afisare(); return 0; }
Output Varianta A Ferma: Ferma Buzias Varianta B Ferma Agricola: Ferma Buzias cu suprafata 300
24
DESTRUCTORII VIRTUALI
Ar trebui ca destructori claselor baz s fie declarai virtuali? De ce da sau de ce nu?
25
DESTRUCTORII VIRTUALI
Ar trebui ca destructori claselor baz s fie declarai virtuali? De ce da sau de ce nu? Da! Trebuie s tergem ntotdeauna i pointerii din subclase (altfel apare riscul de memory leaks)
26
DESTRUCTORII VIRTUALI
class Base1 { public: ~Base1() { std::cout << "~Base1()\n"; } }; class Derived1 : public Base1 { public: ~Derived1() { std::cout << "~Derived1()\n"; } }; class Base2 { public: virtual ~Base2() { std::cout << "~Base2()\n"; } }; class Derived2 : public Base2 { public: ~Derived2() { std::cout << "~Derived2()\n"; } }; int main() { Base1* bp = new Derived1; delete bp; Base2* b2p = new Derived2; delete b2p; }
27
DESTRUCTORII VIRTUALI
class Base1 { public: ~Base1() { std::cout << "~Base1()\n"; } }; class Derived1 : public Base1 { public: ~Derived1() { std::cout << "~Derived1()\n"; } }; class Base2 { public: virtual ~Base2() { std::cout << "~Base2()\n"; } }; class Derived2 : public Base2 { public: ~Derived2() { std::cout << "~Derived2()\n"; } }; int main() { Base1* bp = new Derived1; delete bp; Base2* b2p = new Derived2; delete b2p; }
28
POLIMORFISM
Polimorfismul este abilitatea de a folosi o metod sau un operator n moduri diferite Tipuri de polimorfism Run-time
Motenire i funcii virtuale
Compile-time
Template-uri
Ad-hoc
Supradefinirea operatorilor (operatorul + se comport diferit pentru tipul int i string)
Parametric
29
POSIBLE ERORI
Specificatorul de acces implicit pentru motenire este private. O eroare des ntlnit este de a omite specificatorul de acces public Constructori nu pot fi funcii virtuale
30
SUMAR
Motenirea O metod care permite refolosirea codului Folosirea motenirii publice pentru polimorfism Folosirea motenirii private pentru ncapsulare Polimorfism
31
CURS VIITOR
Funcii pur virtuale Clase abstracte Motenirea multipl Type casting
32