0% found this document useful (0 votes)
43 views

Comp Mostenire

This document discusses class composition, inheritance, and polymorphism in C++. It provides examples of defining base and derived classes, including how constructors and destructors are called during object creation and destruction. It also covers accessing protected and private members of base classes in derived classes, overriding base class functions, and using pointers and references to base class types to refer to derived class objects.

Uploaded by

Anatol Mocan
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
43 views

Comp Mostenire

This document discusses class composition, inheritance, and polymorphism in C++. It provides examples of defining base and derived classes, including how constructors and destructors are called during object creation and destruction. It also covers accessing protected and private members of base classes in derived classes, overriding base class functions, and using pointers and references to base class types to refer to derived class objects.

Uploaded by

Anatol Mocan
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 14

Compoziia i motenirea

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

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.

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:

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

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

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

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

Pointeri si Referinte la motenire.


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.

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

You might also like