Sunteți pe pagina 1din 5

15.

Moştenirea

Clasa care este moştenită este numită clasă de bază. Clasa care moşteneşte este numită clasă derivată. O
clasă derivată poate fi moştenită la rândul ei. Astfel se creează moştenirea multiplă.

public

Când specificatorul de acces al unei clase de bază este public:


- toţi membrii public ai clasei de bază devin membri publici ai clasei derivate,
- toţi membrii protected ai clasei de bază devin membri protected ai clasei derivate,
- în toate cazurile: elementele private ale bazei rămân particulare pentru bază şi nu sunt accesibile membrilor
clasei derivate.

CLASA DE BAZĂ CLASA DERIVATĂ

private private

protected protected
MOŞTENIRE   ACCES
public public
MOŞTENIRE   ACCES

#include<iostream.h>

class B {
int a;
public:
void init_baza(int i) {a = i;}
void arata_baza(){cout<<a<<endl;}
};

class D : public B{
int x;
public:
void init_derivat(int i) {x = i;}
void arata_derivat(){cout<<x<<endl;}
// void arata_baza_din_derivat(){cout<<a<<endl;} //cannot access private member declared in class 'B'
};

void main() {
B b; //obiectul de tip B (baza)
b.init_baza(1); //B are acces la propriile-i metode
b.arata_baza(); //B nu are acces la metodele din D

D d; //obiectul de tip D (derivat)


d.init_baza(2); //D are acces la metodele publice din B
d.arata_baza(); //D are acces la metodele publice din B

d.init_derivat(3); //D are acces la propriile-i metode


d.arata_derivat(); //D are acces la propriile-i metode
}
private

Când clasa de bază este moştenită prin utilizarea specificatorului de acces private:
- toţi membrii public şi protected ai clasei de bază devin membri privaţi ai clasei derivate
CLASA DE BAZĂ CLASA DERIVATĂ

protected private
MOŞTENIRE   ACCES
public
MOŞTENIRE   ACCES
private protected
public

N.B. Când un specificator de acces al unei clase de bază este private, membrii publici sau protejaţi ai bazei devin
membri particulari ai clasei derivate. Aceasta înseamnă că ei sunt încă accesibili membrilor clasei derivate, dar şi
secţiunilor din programul dvs. care nu sunt membri nici ai clasei de bază, nici ai celei derivate.

#include<iostream.h>

class BAZA {
int x;
protected:
int y;
public:
int z;
BAZA(){}
BAZA(int i, int j, int k) {x = i; y = j; z = k;}
void arata_baza() { cout<<x<<" "<<y<<" "<<z<<endl;}
};

class DERIVAT : private BAZA {


int d;
public:
DERIVAT(){}
DERIVAT(int i){d = i;}

// void init_baza_private(int i){x = i;} //error C2248: 'x' : cannot access private member declared in class
'BAZA'
void init_baza_protected(int i){y = i;}
void init_baza_public(int i){z = i;}

// void arata_baza_private(){cout<<x<<endl;} //error C2248: 'x' : cannot access private member declared in
class 'BAZA'
void arata_baza_protected(){cout<<y<<endl;}
void arata_baza_public(){cout<<z<<endl;}
};

void main()
{
DERIVAT d;
d.init_baza_protected(2);
d.init_baza_public(3);

d.arata_baza_protected(); //2
d.arata_baza_public(); //3
}
protected

Când se moşteneşte o clasă de bază ca protected, toţi membrii public şi protected ai clasei de bază devin
membri protejaţi ai clasei derivate.

CLASA DE BAZĂ CLASA DERIVATĂ

protected protected
MOŞTENIRE   ACCES
public
MOŞTENIRE   ACCES
private private
public

Moştenirea din clase de bază multiple

class derivat : public baza1, private baza2, protected baza3 etc.

Constructori, destructori şi moştenire

Când se construieşte un obiect de clasa derivat:


1. construieşte baza
2. construieşte derivat
3. distruge derivat
4. distruge baza

Transmiterea parametrilor spre constructorii clasei de bază

baza(int i) {x = i;}
class derivat : public baza
derivat(int i, int j) : baza(i)

Constructorul lui derivat este declarat aici ca preluând doi parametri, i şi j. Dar derivat() foloseşte doar pe i; j este
pasat către baza(). În general, constructorul clasei derivate trebuie să declare atât parametrul/parametrii care
este/sunt cerut/ceruţi de el, cât şi pe cel/cei ai clasei de bază. Parametrii ceruţi de baza sunt transmişi acesteia prin
constructorul clasei de bază specificate după două puncte.

Pentru clasele de bază multiple:

baza1(int i){x = i;}


baza2(int i){y = i;}
class derivat : public baza 1, public baza2
derivat(int i, int j, int k) : baza1(j), baza2(k)

Aşadar, argumentele unui constructor al clasei de bază sunt transmise prin intermediul argumentelor constructorului
clasei derivate. Chiar în cazul în care constructorul clasei derivate nu preia nici un argument, va fi necesar să declare
unu sau mai multe dacă clasa de bază preia unul sau mai multe argumente. În această situaţie, argumentele transmise
clasei derivate sunt pur şi simplu transferate bazei.

baza1(int i){x = i;}


baza2(int i){y = i;}
class derivat : public baza1, public baza2
derivat(int i, int j) : baza1(i), baza2(j)

ATENŢIE: un argument care este transmis unei clase de bază nu exclude utilizarea sa şi de către o clasă derivată.

baza(int i, int j)
class derivat : public baza
derivat(int i, int j) : baza(i, j)
N.B. Atunci când transmiteţi argumente către constructorii din clasa de bază, argumentele pot să fie orice expresie
validă în acel moment, inclusiv apelări de funcţii şi de variabile. Acest lucru este un aspect al faptului că C++
permite iniţializarea dinamică.

Permiterea accesului

Declararea de acces are forma generală:

clasa-de-baza::membru

Declararea de acces este pusă în antetul de acces corespunzător din declararea clasei derivate. Reţineţi că într-o
declarare de acces nu este necesară (şi nici permisă) o declarare de tip.

class BAZA {
public:
int j; //public in BAZA
};

//Mosteneste BAZA ca particular


class DERIVAT : private BAZA {
public:
//aici se afla declararea accesului
BAZA::j; //face j din nou public
.
.
.
};

Clase de bază virtuale

Când două sau mai multe obiecte sunt derivate dintr-o clasă de bază comună, puteţi preveni prezenţa într-
unul dintre acestea a mai multor copii ale clasei de bază, declarând-o virtual în momentul când ea este moştenită.
Obţineţi aceasta precedând numele clasei de bază cu cuvântul cheie virtual.

#include<iostream.h>

class BAZA {
public:
int i;
};

class DERIVAT_1 : virtual public BAZA {


public:
int j;
};

class DERIVAT_2 : virtual public BAZA {


public:
int k;
};

class DERIVAT_3 : public DERIVAT_1, public DERIVAT_2 {


public:
int sum;
};

void main() {
DERIVAT_3 ob;

ob.i = 10; //acum nu mai este ambiguuu


}
N.B. Chiar dacă atât DERIVAT_1 cât şi DERIVAT_2 specifică BAZA ca fiind virtual, BAZA este încă prezentă în
obiectele de acel tip. De exemplu, următoarea secvenţă este perfect validăş

//defineste o clasa de tipul DERIVAT_1


DERIVAT_1 clasamea;
clasamea.i = 88;

#include<iostream.h>

class BAZA {
public:
int i;
};

class DERIVAT_1 : virtual public BAZA {


public:
int j;
};

class DERIVAT_2 : virtual public BAZA {


public:
int k;
};

class DERIVAT_3 : public DERIVAT_1, public DERIVAT_2 {


public:
int sum;
};

void main() {
DERIVAT_3 d3; d3.i = 33; cout<<d3.i<<endl;
DERIVAT_2 d2; d2.i = 22; cout<<d2.i<<endl;
DERIVAT_1 d1; d1.i = 11; cout<<d1.i<<endl;
BAZA b; b.i = 1; cout<<b.i<<endl;
}