Sunteți pe pagina 1din 3

18.10.

2011

Compoziţia şi moştenirea
Compoziţie
Moştenirea
class A {
Mostenirea este mecanismul prin care un limbaj de
private programare redă relaţiile ierarhice dintre abstracţiuni.
int ax, ay; O clasa care este mostenita se numeste clasa de baza.
public: O clasa care mosteneste este numita clasa derivata.
A() : ax(0), ay(0) {} Clasele alfate intr-o relatie de mostenire formeaza
A(int x, int y) : ax(x), ay(y) { } impreuna o ierarhie de clase.
}; class B { • Forma generala a unei clase aflate intr-o relatie de
private: mostenire (simpla) este:
A a; • class nume-clasa-derivata : specificator-acces
int bz; nume-clasa-baza {
public: // corpul clasei
B(int x=0, int y=0, int z=0) : A(x,y), bz(z) {} };
}

Exemplu comtinuare
• #include <iostream.h • class Imaginary: public Complex {
#include <math.h class Complex {
friend class Imaginary; public:
friend class Double; Imaginary(double i = 0): Complex(0, i) { }
public: Imaginary(const Complex &c): Complex(0, c.ipart) { }
Complex(double r = 0, double i = 0): rpart(r), ipart(i) { } Imaginary& operator=(const Complex &c) {
Complex(const Complex &c): rpart(c.rpart), ipart(c.ipart) { } rpart = 0; ipart = c.ipart; return *this;
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);
} • class Double: public Complex {
friend Complex operator+(double d, const Complex &c) { public:
return c + Complex(d); Double(double re = 0): Complex(re) { }
} Double(const Complex &c): Complex(c.rpart) { }
... Double& operator=(const Complex &c) {
operator double() {
return sqrt(rpart*rpart + ipart * ipart;) rpart = c.rpart; ipart = 0; return *this;
private: }
double rpart, ipart; };
};

Observatii
• In ambele clase derivate (Imaginary si Double) a fost definit cate un operator de
Constructorii si Mostenirea
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 • Ordinea Executiei Constructorilor
acest fapt este prezentata mai jos. La creare unui obiect al unei clase derivate se excuta urmatoarele
operatii:
• Constructorii claselor derivate, apeleaza explicit anumiti constructori ai clasei de • 1. Aloca memorie. Se aloca necesarul de memorie pentru o
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 instanta a acelei clase.
explicat deasmenea intr-una din sectiunile urmatoare ale acestei lucrari. 2. Apeleaza constructorul clasei de baza. Constructorul clasei
derivate, apeleaza automat constructorul clasei sale de baza. Desi
• Specificatorul de acces la clasa de baza modifica statutul in clasa derivata a acest lucru nu necesita interventia programatorului, acesta poate
membrilor din clasa de baza in conformitate cu urmatoarele reguli: interveni pentru a controla apelul contructorului de baza. Daca clasa
• Regula 1: Membrii private din clasa de baza sunt intotdeauna inaccesibili in clasele de baza nu se afla in varful ierarhiei, aceasta va apela la randul ei
derivate. constructorul clasei sale de baza.
• Regula 2: Membrii protected din clasa de baza raman protected daca mostenirea 3. Initializeaza datele-membru de tip obiect. Constructorul clasei
este cu acces public, si devin private daca mostenirea este cu acces private.
derivate va initializa automat datele-membru de tip obiect definite in
• 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. clasa. Acest lucru se face implicit prin invocarea constructorului
implicit pentru acele obiecte. Acest lucru poate fi modificat, prin
• Cand una dintre clasele derivate are nevoie in mod exceptional sa acceseze structura intermediul unei liste de initializare.
interna (declarata privat) a clasei de baza, ea va fi declarata friend in clasa de baza. 4. Executa constructorul clasei derivate. Dupa ce au fost
initializate obiectele membru ale clasei, se executa corpul
constructorului din clasa derivata.

1
18.10.2011

Destructorii si Mostenirea Redefinirea Membrilor din Clasa de Baza.


• Ordinea Executiei Destructorilor • class A {
Destructorii se executa in ordine inversa fata de protected:
double x;
constructori: double y;
• 1. Executa destructorul clasei derivate. public:
A(double xx = 0, double yy = 0) : x(xx), y(yy) {}
2. Distruge datele-mebru nestatice de tip obiect, ...
apeland destructorii pentru aceste obiecte. };
3. Apeleaza constructorul clasei de baza. • class B : public A {
4. Dezaloca memoria. protected:
double x;
double y;
public:
• Invocarea Explicita a Constructorilor Claselor de B(double bx = 0, double by = 0,
Baza double ax = 0, double ay = 0): A(ax,ay) { x = bx; y = by; }
Constructorul clasei Imaginary a fost definit in exemplul void afis() const;
};
de mai sus astfel: • void B::afis() const {
• Imaginary(double i = 0): Complex(0, i) { } cout << "Membrii mosteniti " << A::x << A::y << endl;
cout << "Membrii proprii " << x << y << endl;
}

Redefinirea functiilor-membru.
continuare
• class Auto • class Truck: public Auto
• { • {
• public: // constructori • public: // constructori
• Truck ();
• Auto ();
• Truck (int engine_wt, int sp, char const *nm, int trailer_wt);
• Auto (int wt, int sp, char const *nm); • void setname (char const *nm);
• Auto (Auto const &other); // constructorul copy • int getweight () const;
• Auto const &operator= (Auto const &other); // asignarea • private: // data
• ~Auto (); // destructorul • int trailer_weight;
• };
• // interfata
• // examplu de constructor
• char const *getname () const; • Truck::Truck (int engine_wt, int sp, char const *nm,
• void setname (char const *nm); • int trailer_wt): Auto (engine_wt, sp, nm)
• private: // data • {
• char const *name; • trailer_weight = trailer_wt;
• }
• };

Pointeri si Referinte la moştenire. Exemplu


• class Patrulater {
• Doua Avantaje ale Pointerilor protected:
• double laturi[4];
1.Un pointer la clasa de baza poate indica spre orice obiect al unei public:
clase derivate - direct sau indirect - din ea. Patrulater(double l1=0.0, double l2=0.0, double l3=0.0,
Daca declaram un pointer la un obiect al unei clase, putem utiliza double l4=0.0) {
acel pointer pentru a pastra adresa unui obiect al oricarei clase laturi[0] = l1; laturi[1] = l2;
derivate din ea. laturi[2] = l3; laturi[3] = l4;
}
2. Functiile membru apelate prin pointeri pot fi selectate la executie double perimetru() {
(daca sunt declarate virtuale) in loc sa fie selectate la compilare. return laturi[0]+ laturi[1]+laturi[2]+laturi[3];
}
• Observatie: Daca pentru un obiect se defineste si o variabila de tip };
referinta, iar functiile-membru sunt apelate prin intermediul class Dreptunghi : public Patrulater {
referintei, atunci selectarea functiei se va face deasemenea la public:
executie si nu la compilare. In schimb apelul functiilor membru prin Dreptunghi(double l1=0.0, double l2=0.0) :
intermediul operatorului punct (obiect.functie() ) nu ofera aceasta Patrulater(l1,l2,l1,l2) {}
flexibilitate. double perimetru() { return 2*(laturi[0]+laturi[1]); }
double arie() { return laturi[0]* laturi[1]; }
};

2
18.10.2011

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);
• }

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