Motenirea claselor II Programarea calculatoarelor i limbaje de
Moştenirea claselor (II) Programarea calculatoarelor şi limbaje de programare II Capitolul 6
Obiective n Înţelegerea modului în care se utilizează constructorii şi destructorii în clasele derivate n Studierea modului în care se foloseşte moştenirea multiplă pentru a deriva o clasă din mai multe clase de bază
Sumar n Constructorii şi destructorii în clasele derivate n Observaţii legate de conversia implicită a obiectelor din clasele derivate la obiectele din clasa de bază n Relaţiile „uses a” şi „knows a” n Studiu de caz: clasele Point, Circle şi Cylinder n Moştenirea multiplă
Constructorii şi destructorii în clasele derivate n O clasă derivată moşteneşte membrii clasei de bază când este instanţiat un obiect din clasa derivată trebuie apelat constructorul clasei de bază pentru a iniţializa membrii care provin din clasa de bază n dacă nu este apelat explicit constructorul, pentru membrii care provin din clasa de bază se apelează automat constructorul implicit al clasei de bază n
Constructorii şi destructorii în clasele derivate n Nu se moştenesc în clasele derivate n constructorii claselor de bază n operatorii de asignare din clasele de bază n Constructorul unei clase derivate apelează întotdeauna mai întâi constructorii claselor de bază sau, în lipsa acestor apeluri, constructorii impliciţi pentru clasele de bază n Destructorii se apelează în ordine inversă apelurilor constructorilor n constructorii claselor derivate sunt apelaţi înaintea constructorilor claselor de bază
Constructorii şi destructorii în clasele derivate n Să presupunem că folosim o clasa derivată şi o clasa de bază, ambele conţinând obiecte altor clase n Atunci când se creează un obiect dintr-o astfel de clasă derivată, automat se apelează: 1. 2. 3. 4. constructorii obiectelor din clasa de bază constructorul clasei de bază constructorii obiectelor din clasa derivată constructorul clasei derivate n Destructorii se apelează, conform regulii enunţate mai sus, în ordinea inversă constructorilor
Constructorii şi destructorii în clasele derivate n Pentru clasele care conţin obiecte altor clase, ordinea de iniţializare a obiectelor membre este ordinea în care acestea sunt declarate în clase n Ordinea în care sunt listate iniţializările în lista de iniţializare a constructorilor nu afectează această ordine
Constructorii şi destructorii în clasele derivate n Exemplu n Demonstrează ordinea de apel al constructorilor şi al destructorilor pentru clasele de bază şi cele derivate class Point { public: Point(int = 0, int = 0); //constructor implicit ~Point(); //destructor protected: //accesibil din clasele derivate int x, y; //x si y coordonatele unui punct };
Constructorii şi destructorii în clasele derivate class Circle : public Point { public: //constructor implicit Circle(double r = 0. 0, int x = 0, int y = 0); ~Circle(); protected: double radius; }; Circle: : Circle(double r, int a, int b) : Point(a, b) { radius = r; //ar trebui validata cout << "Constructorul obiectului Circle: raza este " << radius << " [" << x << ", " << y << ']' << endl; }
Constructorii şi destructorii în clasele derivate int main() Constructorul obiectului Point: [11, 22] { Destructorul obiectului Point: [11, 22] { Point p(11, 22); } Constructorul obiectului Point: [72, 29] Constructorul obiectului Circle: raza este 4. 5 [72, 29] cout << endl; Circle circle 1(4. 5, 72, 29); cout << endl; Circle circle 2(10, 5, 5); cout << endl; return 0; } Destructorul obiectului Circle: raza este 4. 5 [72, 29] Destructorul obiectului Point: [72, 29]
Sumar n Constructorii şi destructorii în clasele derivate n Observaţii legate de conversia implicită a obiectelor din clasele derivate la obiectele din clasa de bază n Relaţiile „uses a” şi „knows a” n Studiu de caz: clasele Point, Circle şi Cylinder n Moştenirea multiplă
Obiecte din clasele derivate convertite implicit la obiecte din clasa de bază n Obiectele clasei derivate pot fi tratate ca obiecte ale clasei de bază n clasa derivată are membri corespunzători tuturor membrilor clasei de bază n Asignarea în sens invers, a unui obiect din clasa de bază unui obiect din clasa de derivată nu este permisă în mod implicit n n ar lăsa nedefiniţi membrii adiţionali ai clasei derivate această asignare ar putea fi implementată prin supraîncărcarea operatorului de asignare sau a constructorului de conversie
Obiecte din clasele derivate convertite implicit la obiecte din clasa de bază n Moştenirea public permite ca un pointer la un obiect dintr-o clasă derivată să fie convertit implicit într-un pointer la un obiect al clasei sale de bază n un obiect al clasei derivate este şi obiect al clasei de bază
Sumar n Constructorii şi destructorii în clasele derivate n Observaţii legate de conversia implicită a obiectelor din clasele derivate la obiectele din clasa de bază n Relaţiile „uses a” şi „knows a” n Studiu de caz: clasele Point, Circle şi Cylinder n Moştenirea multiplă
Relaţiile „uses a” şi „knows a” n Tehnici care încurajează reutilizarea codului n moştenirea n compunerea claselor n Există şi alte moduri în care se pot folosi serviciile claselor n Exemplu Un obiect persoană nu este o maşină n Un obiect persoană nu conţine o maşină n Un obiect persoană foloseşte o maşină n
Relaţiile „uses a” şi „knows a” n Relaţia „uses a” n O funcţie foloseşte un obiect prin simplul apel al unei funcţii membre non-private a obiectului prin intermediul n n n unui pointer al unei referinţe al obiectului însuşi n Relaţia „knows a” – asocierea claselor n Un obiect poate conţine un pointer sau o referinţă pentru accesul la celălalt obiect
Relaţiile „uses a” şi „knows a” n Diferenţa dintre compunere şi asociere n Compunere: obiectele au aceeaşi perioadă de existenţă n Asociere: obiectele pot exista în mod independent
Sumar n Constructorii şi destructorii în clasele derivate n Observaţii legate de conversia implicită a obiectelor din clasele derivate la obiectele din clasa de bază n Relaţiile „uses a” şi „knows a” n Studiu de caz: clasele Point, Circle şi Cylinder n Moştenirea multiplă
Studiu de caz: clasele Point, Circle şi Cylinder n Exemplu n Clasa Cylinder din clasa Circle n Clasa Circle este derivată din clasa Point class Point { friend ostream& operator<<(ostream&, const Point&); public: Point(int = 0, int = 0); void set. Point(int, int); int get. X() const { return x; } int get. Y() const { return y; } protected: int x, y; };
Studiu de caz: clasele Point, Circle şi Cylinder class Circle : public Point { friend ostream& operator<<(ostream&, const Circle&); public: Circle(double r = 0. 0, int x = 0, int y = 0); void set. Radius(double); double get. Radius() const; double area() const; protected: double radius; };
Studiu de caz: clasele Point, Circle şi Cylinder class Cylinder : public Circle { friend ostream& operator<<(ostream&, const Cylinder&); public: Cylinder(double h = 0. 0, double r = 0. 0, int x = 0, int y = 0); void set. Height(double); double get. Height() const; double area() const; double volume() const; protected: double height; };
Studiu de caz: clasele Point, Circle şi Cylinder Point: : Point(int a, int b) { set. Point(a, b); } Circle: : Circle(double r, int a, int b) : Point(a, b) { set. Radius(r); } Cylinder: : Cylinder(double h, double r, int x, int y) : Circle(r, x, y) { set. Height(h); } n Constructorul clasei Cylinder trebuie să invoce constructorul clasei sale de bază directe care este Circle n Nu trebuie să invoce constructorul clasei de bază indirecte Point
Studiu de caz: clasele Point, Circle şi Cylinder int main() { Cylinder cyl(5. 7, 2. 5, 12, 23); cyl este afişat ca un Point. . . Point& p. Ref = cyl; cout << "n. Cilindrul tiparit ca un Point este: " << p. Ref << "nn"; Circle& cout << << << circle. Ref = cyl; "Cilindrul tiparit ca un Circle este: n" circle. Ref "n. Aria: " << circle. Ref. area() << endl; return 0; } cyl este afişat ca un Circle
Sumar n Constructorii şi destructorii în clasele derivate n Observaţii legate de conversia implicită a obiectelor din clasele derivate la obiectele din clasa de bază n Relaţiile „uses a” şi „knows a” n Studiu de caz: clasele Point, Circle şi Cylinder n Moştenirea multiplă
Moştenirea multiplă n O clasă poate să fie derivată din mai multe clase de bază n clasa derivată moşteneşte membri de la mai multe clase de bază n Moştenirea multiplă se poate folosi atunci când există o relaţie de tip „is a” între un nou tip de dată şi mai multe tipuri existente n Acest mecanism poate cauza o serie de ambiguităţi
Moştenirea multiplă n Exemplu class Base 1 { public: Base 1(int x){ value = x; } int get. Data() const { return value; } protected: int value; };
Moştenirea multiplă class Base 2 { public: Base 2(char c){ letter = c; } char get. Data() const { return letter; } protected: char letter; };
Moştenirea multiplă class Derived : public Base 1, public Base 2 { friend ostream& operator<<(ostream &, const Derived&); public: Derived(int, char, double); double get. Real() const; private: double real; }; Derived: : Derived(int i, char c, double f) : Base 1(i), Base 2(c), real(f){}
Moştenirea multiplă int main() { Base 1 b 1(10), *base 1 Ptr = 0; Base 2 b 2('Z'), *base 2 Ptr = 0; Derived d(7, 'A', 3. 5); . . . cout << "Datele membre ale lui Derived pot fi" << " accesate individual: " << "n Intreg: " << d. Base 1: : get. Data() << "n Caracter: " << d. Base 2: : get. Data() << "n. Numar real: " << d. get. Real() << "nn"; return 0; } Rezolvarea ambiguităţii la apelul funcţiei get. Data() definită în Base 1 şi Base 2
Moştenirea multiplă int main() { Base 1 b 1(10), *base 1 Ptr = 0; Base 2 b 2('Z'), *base 2 Ptr = 0; Derived d(7, 'A', 3. 5); . . . cout << "Derived poate fi tratat ca un obiect" << " al claselor de baza: n"; base 1 Ptr = &d; cout << "base 1 Ptr->get. Data() afiseaza " << base 1 Ptr->get. Data() << 'n'; . . . return 0; } Relaţie „is a” în moştenirea multiplă: Obiectul d este tratat ca un Base 1
- Slides: 30