Comp Mostenire

14
Compoziţia şi moştenirea

description

Mostenire C++

Transcript of Comp Mostenire

Page 1: Comp Mostenire

Compoziţia şi moştenirea

Page 2: Comp Mostenire

Compoziţie

class A { privateint ax, ay;

public: A() : ax(0), ay(0) {} A(int x, int y) : ax(x), ay(y) { }

}; class B { private:A a; int bz;

public:B(int x=0, int y=0, int z=0) : A(x,y), bz(z) {}

}

Page 3: Comp Mostenire

MoştenireaMostenirea este mecanismul prin care un limbaj de

programare redă relaţiile ierarhice dintre abstracţiuni.

O clasa care este mostenita se numeste clasa de baza.

O clasa care mosteneste este numita clasa derivata. Clasele alfate intr-o relatie de mostenire formeaza impreuna o ierarhie de clase.

• Forma generala a unei clase aflate intr-o relatie de mostenire (simpla) este:

• class nume-clasa-derivata : specificator-acces nume-clasa-baza {

// corpul clasei};

Page 4: Comp Mostenire

Exemplu

• #include <iostream.h#include <math.h class Complex {friend class Imaginary;friend class Double;public:

Complex(double r = 0, double i = 0): rpart(r), ipart(i) { }Complex(const Complex &c): rpart(c.rpart), ipart(c.ipart) { }Complex& operator=(const Complex &c) {

rpart = c.rpart; ipart = c.ipart; return *this;}Complex operator+(const Complex &c) const {

return Complex(rpart + c.rpart, ipart + c.ipart);}friend Complex operator+(double d, const Complex &c) {

return c + Complex(d);}...operator double() {

return sqrt(rpart*rpart + ipart * ipart;)private:

double rpart, ipart;};

Page 5: Comp Mostenire

comtinuare

• class Imaginary: public Complex {public:

Imaginary(double i = 0): Complex(0, i) { }Imaginary(const Complex &c): Complex(0, c.ipart) { }Imaginary& operator=(const Complex &c) {

rpart = 0; ipart = c.ipart; return *this;}

};

• class Double: public Complex {public:

Double(double re = 0): Complex(re) { }Double(const Complex &c): Complex(c.rpart) { }Double& operator=(const Complex &c) {

rpart = c.rpart; ipart = 0; return *this;}

};

Page 6: Comp Mostenire

Observatii

• In ambele clase derivate (Imaginary si Double) a fost definit cate un operator de atribuire avand ca operand drept un obiect al clasei de baza, pentru a caror implementare a fost necesar accesul la structura privata a clasei de baza. Din acest motiv cele doua clase au fost declarate ca friend in clasa de baza. Discutia legata de acest fapt este prezentata mai jos.

• Constructorii claselor derivate, apeleaza explicit anumiti constructori ai clasei de baza. Relatia intre constructorii/destructorii clasel de baza si ai celor derivate, precum si cazul in care este necesar apelul explicit al constructorilor clasei de baza este explicat deasmenea intr-una din sectiunile urmatoare ale acestei lucrari.

• Specificatorul de acces la clasa de baza modifica statutul in clasa derivata a membrilor din clasa de baza in conformitate cu urmatoarele reguli:

• Regula 1: Membrii private din clasa de baza sunt intotdeauna inaccesibili in clasele derivate.

• Regula 2: Membrii protected din clasa de baza raman protected daca mostenirea este cu acces public, si devin private daca mostenirea este cu acces private.

• Regula 3: Membrii public din clasa de baza raman public daca mostenirea este cu acces public, si devin private daca mostenirea este cu acces private.

• Cand una dintre clasele derivate are nevoie in mod exceptional sa acceseze structura interna (declarata privat) a clasei de baza, ea va fi declarata friend in clasa de baza.

Page 7: Comp Mostenire

Constructorii si Mostenirea

• Ordinea Executiei ConstructorilorLa creare unui obiect al unei clase derivate se excuta urmatoarele operatii:

• 1. Aloca memorie. Se aloca necesarul de memorie pentru o instanta a acelei clase. 2. Apeleaza constructorul clasei de baza. Constructorul clasei derivate, apeleaza automat constructorul clasei sale de baza. Desi acest lucru nu necesita interventia programatorului, acesta poate interveni pentru a controla apelul contructorului de baza. Daca clasa de baza nu se afla in varful ierarhiei, aceasta va apela la randul ei constructorul clasei sale de baza. 3. Initializeaza datele-membru de tip obiect. Constructorul clasei derivate va initializa automat datele-membru de tip obiect definite in clasa. Acest lucru se face implicit prin invocarea constructorului implicit pentru acele obiecte. Acest lucru poate fi modificat, prin intermediul unei liste de initializare. 4. Executa constructorul clasei derivate. Dupa ce au fost initializate obiectele membru ale clasei, se executa corpul constructorului din clasa derivata.

Page 8: Comp Mostenire

Destructorii si Mostenirea

• Ordinea Executiei DestructorilorDestructorii se executa in ordine inversa fata de constructori:

• 1. Executa destructorul clasei derivate.2. Distruge datele-mebru nestatice de tip obiect,apeland destructorii pentru aceste obiecte. 3. Apeleaza constructorul clasei de baza.4. Dezaloca memoria.

• Invocarea Explicita a Constructorilor Claselor de BazaConstructorul clasei Imaginary a fost definit in exemplul de mai sus astfel:

• Imaginary(double i = 0): Complex(0, i) { }

Page 9: Comp Mostenire

Redefinirea Membrilor din Clasa de Baza.

• class A {protected:double x;double y;

public:A(double xx = 0, double yy = 0) : x(xx), y(yy) {}...

};

• class B : public A {protected:double x;double y;

public:B(double bx = 0, double by = 0,double ax = 0, double ay = 0): A(ax,ay) { x = bx; y = by; }

void afis() const;};

• void B::afis() const {cout << "Membrii mosteniti " << A::x << A::y << endl;cout << "Membrii proprii " << x << y << endl;

}

Page 10: Comp Mostenire

Redefinirea functiilor-membru.

• class Auto

• {

• public: // constructori

• Auto ();

• Auto (int wt, int sp, char const *nm);

• Auto (Auto const &other); // constructorul copy

• Auto const &operator= (Auto const &other); // asignarea

• ~Auto (); // destructorul

• // interfata

• char const *getname () const;

• void setname (char const *nm);

• private: // data

• char const *name;

• };

Page 11: Comp Mostenire

continuare

• class Truck: public Auto

• {

• public: // constructori

• Truck ();

• Truck (int engine_wt, int sp, char const *nm, int trailer_wt);

• void setname (char const *nm);

• int getweight () const;

• private: // data

• int trailer_weight;

• };

• // examplu de constructor

• Truck::Truck (int engine_wt, int sp, char const *nm,

• int trailer_wt): Auto (engine_wt, sp, nm)

• {

• trailer_weight = trailer_wt;

• }

Page 12: Comp Mostenire

Pointeri si Referinte la moştenire.

• Doua Avantaje ale Pointerilor

•1.Un pointer la clasa de baza poate indica spre orice obiect al unei clase derivate - direct sau indirect - din ea.

Daca declaram un pointer la un obiect al unei clase, putem utiliza acel pointer pentru a pastra adresa unui obiect al oricarei clase derivate din ea.

2. Functiile membru apelate prin pointeri pot fi selectate la executie(daca sunt declarate virtuale) in loc sa fie selectate la compilare.

• Observatie: Daca pentru un obiect se defineste si o variabila de tip referinta, iar functiile-membru sunt apelate prin intermediul referintei, atunci selectarea functiei se va face deasemenea la executie si nu la compilare. In schimb apelul functiilor membru prin intermediul operatorului punct (obiect.functie() ) nu ofera aceasta flexibilitate.

Page 13: Comp Mostenire

Exemplu

• class Patrulater {protected: double laturi[4];

public:Patrulater(double l1=0.0, double l2=0.0, double l3=0.0,

double l4=0.0) { laturi[0] = l1; laturi[1] = l2;laturi[2] = l3; laturi[3] = l4;

} double perimetru() {return laturi[0]+ laturi[1]+laturi[2]+laturi[3]; }

}; class Dreptunghi : public Patrulater {

public: Dreptunghi(double l1=0.0, double l2=0.0) :

Patrulater(l1,l2,l1,l2) {} double perimetru() { return 2*(laturi[0]+laturi[1]); } double arie() { return laturi[0]* laturi[1]; }

};

Page 14: Comp Mostenire

continuare

• class Patrat : public Patrulater { public: Patrat(double l1 = 0.0) : Patrulater(l1,l1,l1,l1) {} double perimetru() { return 4*laturi[0]; } double arie() { return laturi[0]*laturi[0]; } };

• void f(Patrulater &p) { ... }

• Main()

• {

• Patrulater *ppater, pater; Dreptunghi *pdrept, drept; Patrat *ppatrat, patrat;

• pdrept = &drept;ppatrat = &patrat;

• // dar si atribuirile ...

• ppater = &drept; // atribuie adresa pater = patrat; // atribuite obiect

• f(drept);

• }