Comp Mostenire
Comp Mostenire
Compoziie
class A {
private
int 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) {}
}
Motenirea
Mostenirea este mecanismul prin care un limbaj de
programare red relaiile ierarhice dintre abstraciuni.
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
};
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;
};
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;
}
};
Observatii
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.
Constructorii si Mostenirea
Ordinea Executiei Constructorilor
La 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.
Destructorii si Mostenirea
Ordinea Executiei Destructorilor
Destructorii 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
Baza
Constructorul clasei Imaginary a fost definit in exemplul
de mai sus astfel:
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;
};
continuare
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.
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]; }
};
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);
}