Documente Academic
Documente Profesional
Documente Cultură
Mecanismul motenirii
Modul de declarare a claselor derivate
Constructorii claselor derivate
Motenirea simpl
public
protected
private
public, protected
sau private
clas derivat
Clasa A
Clasa B
185
CAPITOLUL 12
Cnd o clas motenete membrii unei alte clase, membrii clasei de baz devin membrii ai clasei derivate.
Motenirea protejat este intermediar celei publice i celei private. n cazul motenirii protejate, comparativ
cu motenire privat, singura diferen este c membrii publici ai clasei de baz devin protejai n timpul
derivrilor ulterioare. n funcie de modificatorii de acces la membrii clasei de baz, la membrii clasei
derivate i de tipul motenirii, lucrurile se pot rezuma astfel (tabelul 12.1.):
Tabelul 12.1.
Modificator
acces la membrii
clasei de baz
private
public
protected
Accesul n clasa
derivat (noul acces)
dobndit prin motenire
public
private
public
protected
private
protected
protected
private
private
private
Aa cum se observ, n toate cazurile, elementele private ale clasei de baz rmn particulare acesteia i nu
sunt accesibile claselor derivate; cele protejate sunt accesibile clasei derivate.
Exemplu: Declararea clasei derivate interfa, cu clasele de baz fereastr i meniu (motenire
multipl):
class fereastra{
//membrii clasei
};
class meniu{
//membrii clasei
};
class interfata: public fereastra, public meniu{
//membrii clasei
};
n ceea ce privete folosirea (compilarea i editarea de legturi) clasei derivate n sensul programrii, clasa de
baz i cea derivat pot apare n acelai fisier surs, sau declarate n fiiere diferite (figura 12.1.).
186
CAPITOLUL 12
declararea clasei derivate. La distrugerea obiectelor, se apeleaz nti destructorul clasei derivate, apoi
destructorii claselor de baz.
Transmiterea argumentelor unei funcii constructor din clasa de baz se face folosind o form extins a
declaraiei constructorului clasei derivate, care transmite argumentele unui sau mai multor constructori din
clasa de baz.
n general, clasele utilizeaz constructori definii de programator. n cazul n care acetia lipsesc,
compilatorul genereaz automat un constructor implicit pentru clasa respectiv. Acelai lucru se ntmpl i
n cazul constructorilor de copiere.
La instanierea unui obiect din clas derivat, o parte din valorile primite ca parametri folosesc la iniializarea
datelor membru ale claselor de baz, iar restul iniializeaz datele membru specifice clasei derivate.
Declararea
clasei de baz
Compilare
Modul obiect al
clasei de baz
Definirea
clasei de baz
Declararea
clasei derivate
Editare
de
legturi
Modul obiect al
clasei derivate
Compilare
Fiier
executabil
Definirea
clasei derivate
Programul de test
(utilizeaz cele
dou tipuri)
Modul obiect al
programului de
test
Compilare
clasa baz
#include <iostream.h>
private
protected
public
class baz
{
int a;
clasa deriv3
clasa deriv2
clasa deriv1
protected:
double w;
void seteaz_a(int a1){a=a1;}
Figura 12.2. Ierarhie de clase
void seteaz_w(int w1){w=w1;}
public:
int c;
baza (int a1, double w1, int c1)
{a=a1; w=w1; c=c1;cout<<"Constructor cls. baz\n";}
~baz()
{cout<<"Destructor baz\n";}
void arat()
187
CAPITOLUL 12
188
CAPITOLUL 12
Constructor deriv1
Constructor deriv2
Constructor deriv3
// x=1 1.23
2 (x.a, x.w, x.c)
// z=3.45 4 5
// v=5.67 6 7
// x.calcul()=4.23
// y.calcul()=9.34
// z.calcul()=12.45
cout<<"x.calcul()="<<x.calcul()<<'\n';
cout<<"y.calcul()="<<y.calcul()<<'\n';
cout<<"z.calcul()="<<z.calcul()<<'\n';
// v.calcul()=18.67
// x.c=2
// y.c=3
Destructor baza
ptr. v
Destructor baza
ptr. z
Destructor baza
ptr. y
ptr x */
cout<<"v.calcul()="<<v.calcul()<<'\n';
cout<<"x.c="<<x.c<<'\n';
cout<<"y.c="<<y.c<<'\n';
/*
Destructor deriv3
Destructor deriv2
Destructor deriv1
Destructor baza
Observaii:
n clasa de baz data membr a este private, w este protected i c este public. n clasa de baz, ct i
n clasele derivate exist constructori care iniializeaz datele membru. Membrii private dintr-o clas de
baz (clasa baz, n cazul nostru) pot fi folosii doar n cadrul acesteia (de metodele sale), nu i n clasele
derivate.
Clasa deriv1:
Membrii privai motenii din clasa baz sunt inaccesibili (a exist, dar este ncapsulat). Pentru a
putea fi accesai, se folosesc metodele clasei baz (metoda calcul). Deoarece n clasa deriv1
exist o metod cu acelai nume cu al unei metode din clasa de baz (redefinirea unei metode n
clasa derivat), se folosete operatorul de rezoluie.
baza::calcul( )
sau
y.baza::calcul( )
Clasa deriv2:
Deoarece motenirea este protejat, membrii publici sau protejai din clasa baz devin protejai n
clasa deriv2. De aceea, dac n funcia main am ncerca folosirea :
cout<<z.baza::calcul( )
, metoda calcul inaccesibil, ea devenind protejat n
clasa deriv3.
Clasa deriv3:
Deoarece motenirea este privat, membrii public sau protected din clasa baz au devenit privai n
clasa deriv3. Se pot folosi toi membrii clasei de baz, cu excepia celor privai (a).
La construirea unui obiect dintr-o clas derivat din clasa baz, se apeleaz mai nti constructorul din clasa
de baz, apoi constructorul clasei derivate Astfel, un obiect y din clasa deriv2 incorporeaz un obiect deja
iniializat cu ajutorul constructorului din clasa baz.
Dac pentru clasa deriv1 defineam un constructor de forma:
deriv1(int a1, double b1, int c1, int b1){a=a1; b=b1; c=c1; d=d1;}
nu era corect, deoarece clasa baz nu are constructori fr parametri, deci nu exist constructor implicit, iar
data a este inaccesibil n deriv1. Apelarea constructorului se realizeaz apelnd explicit constructorul din
clasa baz.
Exerciiu: Fie clasa punct i clasa punct colorat, derivat din clasa punct. Metoda afisare este redefinit
n clasa derivat (punct_col).
#include <iostream.h>
#include <conio.h>
189
CAPITOLUL 12
Crearea ierahiilor de clase
class punct{
int x, y;
//date membru private, inaccesibile n clasa punct_col
public:
punct (int abs=0, int ord=0)
{x=abs; y=ord; cout<<"Constr punct "<<x<<","<<y<<'\n';}
punct (const punct& p)
{x=p.x; y=p.y; cout<<"Constr copiere punct ";
cout<<x<<","<<y<<"\n";}
~punct()
{cout<<"Destr punct "<<x<<","<<y<<"\n";}
void afisare()
{cout<<"P("<<x<<","<<y<<")\n";}
};
class punct_col:public punct{
short cul; //date membru private
public:
punct_col (int, int, short);
punct_col (const punct_col & p):punct (p)
{cul=p.cul; cout<<"Constr copiere punct col "<<cul<<'\n';}
~punct_col()
{cout<<"Destr punct colorat "<<cul<<"\n";}
void afisare()
{cout<<"-----------------\n";
cout<<"Punct colorat:";punct::afisare();
cout<<"Culoare:"<<cul<<"\n-------------------\n";}
};
punct_col::punct_col(int abs=0, int ord=0, short cl=1):punct(abs, ord)
{cul=cl; cout<<"Constr punct colorat "<<"culoare="<<cul<<'\n';}
void main()
{clrscr();
punct_col A(10, 15, 3); //Constr punct 10,15
punct_col B(2,3);
//Constr punct 2,3
punct_col C(12);
//Constr punct 12,0
punct_col D;
// Constr punct 0,0
D.afisare();
/*----------------Punct colorat:P(0,0)
Culoare:1
------------------- */
D.punct::afisare();
punct_col *pp;
pp=new punct_col(12,25);
CAPITOLUL 12
:
Exerciiu: Se implementeaz ierahia de clase din figura 12.3.
Clasele persoana, student, student_bursier au ca date membre
date de tipul ir (implementat n capitolul 11).
#include "sir.cpp"
#include <conio.h>
#include <iostream.h>
class persoan {
protected:
ir numele,prenumele;
char sexul;
public:
persoana ()
//constructor vid
{numele="";prenumele="";sexul='m';
cout<<"Constr PERS vid!\n";}
persoan(const ir&,const ir&,const char);
persoana
sir numele, prenumele
char sexul
student
sir facultatea, specializarea
int anul, grupa
student_bursier
char tipul_bursei
//constructor
};
Figura 12.3.
persoan (const persoana&);
//constr. copiere
virtual ~persoan();
//destructor
const ir& nume()const;
const ir&prenume() const;
char sex() const;
virtual void afiare();
friend ostream & operator<<(ostream &, const persoana &);
friend istream & operator>>(istream &, persoana &);
CAPITOLUL 12
};
CAPITOLUL 12
/* TEMA
student_bursier(student&,char);
student_bursier(const student_bursier&);*/
Construct STUD 2!
s.afisare();cout<<'\n';
/* POP ION
cout<<"Apasa tasta...\n";getch();
student s1(s);
cout<<s1<<'\n';
/* Nume stud:POP
Specializare :EA
Prenume stud:ION
Sex stud:BARBATESC Facultate :N.I.E.
Anul :1 Grupa :2311*/
cout<<"Apasa tasta...\n";getch();
student s3("STAN", "POPICA", 'm', "MECANICA", "I.M.T.", 1, 320);
Prenume stud:ION
Sex stud:BARBATESC
Anul :1 Grupa :2311 */
s3=s1;
cout<<"In urma atribuirii s3="<<s3<<'\n';
Observaii:
193
CAPITOLUL 12
1. S se completeze exemplul cu funciile date ca tem. S se completeze programul de test (funcia main).
2. Funcia afiare este declarat virtual n clasa de baz i redefinit n clasa derivat. Redefinirea
funciei n clasa derivat are prioritate fa de definirea funciei din clasa de baz. Astfel, o funcie
virtual declarat n clasa de baz acioneaz ca un substitut pentru pstrarea datelor care specific o
clas general de aciuni i declar forma interfeei. Funcia afiare are acelai prototip pentru toate
clasele n care a fost redefinit (vezi paragraful 12.7.).
/* Destructor derivat 1 2
Destructor baz2 2
194
Destructor baz1 1 */
CAPITOLUL 12
}
Aa cum ilustreaz exemplul, la declararea obiectului obiect de tipul derivat s-au apelat constructorii
claselor de baz (baz1 i baz2), n ordinea n care apar n declararea clasei derivate: mai nti
constructorul clasei baz1, n care x este dat membru protejat (accesibil din clasa derivat); apoi
constructorul clasei baz2 , n care y este dat membru protejat (accesibil din clasa derivat); apoi
constructorul clasei derivat care le ncorporeaz pe acestea ntr-un singur obiect. Clasa derivat nu are date
membre, ci doar metode (figura 12.5.).
Dup ieirea din blocul n care a fost declarat variabila
obiect, se apeleaz automat destructorii, n ordine
invers apelrii constructorilor.
obiect
7
8
{x=xx; y=yy;}
195
CAPITOLUL 12
La declararea unui obiect din clasa D, membrii clasei A (int a) sunt motenii de obiectul din clasa D n dublu
exemplar (figura 12.7.). Pentru a evita aceast situaie, clasa A va fi declarat virtual, pentru clasele
derivate B i C. Metoda arat este redefinit n clasele B,C, D (polimorfism) (vezi exerciiul urmtor
i figura 12.8.).
x (obiect din clasa D)
Clasa A
int a
Clasa B
int b
Clasa C
int c
int a
int a
int b
int c
Clasa D
int d
int d
Figura 12.6.
Figura 12.7.
Exerciiu:
#include <iostream.h>
class A{
int a;
public:
A(int aa)
{a=aa; cout<<"Constructor A"<<a<<'\n';}
~A()
{cout<<Destructor A;}
void arat()
{cout<<"A.a="<<a<<'\n';}
};
class B: virtual public A{
int b;
public:
B(int bb, int aa=0):A(aa)
{b=bb;cout<<"Constructor B"<<b<<'\n';}
~B()
{cout<<Destructor B;}
void arata()
{cout<<"B.b="<<b<<'\n';}
};
class C: virtual public A{
int c;
public:
C (int cc, int aa=0):A(aa)
{c=cc; cout<<"Constructor C"<<c<<'\n';}
~C()
{cout<<Destructor C;}
void arata()
{cout<<"C.c="<<c<<'\n';}
};
class D: public B, public C{
int d;
196
CAPITOLUL 12
Crearea ierahiilor de clase
public:
D(int aa, int bb, int cc, int dd):A(aa), B(bb), C(cc)
{d=dd;cout<<"Constructor D"<<d<<'\n';}
~D()
{cout<<Destructor D;}
void arat()
{cout<<"D.d="<<d<<'\n';}
};
void main()
{
D x(1,2,3,4); /* Constructor A1 Constructor B2 Constructor C3 Constructor D4 */
x.arat(); // apelul metodei arat din clasa D, pentru obiectul x
D.d=4
x.B::arat();
// apelul metodei arat din clasa B
B.b=2
x.C::arat();
// apelul metodei arat din clasa C
C.c=3
x.A::arat();
// apelul metodei arat din clasa A
A.a=1
}
/* Destructor D
Destructor C
Destructor B
Destructor A */
int b
int c
int d
10
9
Constructor B 7
8
Constructor C 12
31
Constructor B 9
// ConstructorD 35
// Se apeleaz metoda arat, pentru obiectul curent
u.arat();
// A.a=10
v1.arat();
// B.b=7
v2.arat();
// C.c=12
w.arat();
// D.d=35
- ptr. obiectul u, de tp A
- ptr. obiectul v1, de tip B
- ptr. obiectul v2, de tip C
Constructor C 14
- ptr. obiectul w, de tip D
/* Destructor D
Destructor C
Destructor B
Destructor A
- ptr. obiectul w
- ptr. obiectul v2
- ptr. obiectul v1
- ptr. obectul u */
Destructor C
Destructor A
Destructor A
Destructor B
Destructor A
Aa cum se observ din exemplu, metoda arat din clasa de baz A a fost redefinit n clasele derivate B,
C, D. n plus, metoda are aceeai semntur n toate clasele. Dac nu ar fi fost redefinit n clasele derivate,
metoda arat (public) din clasa de baz A ar fi fost motenit de clasele derivate; redefinirea a fost
necesar pentru a putea vizualiza i datele membre proprii claselor derivate. n cazul de fa, identificarea
197
CAPITOLUL 12
metodei apelate se realizeaz chiar n etapa compilrii, datorit legturii cu obiectul pentru care a fost
apelat. De exemplu, la apelul w.arat() se aplic metoda din clasa D (obiectul w este de tip D).
Concluzionnd, identificarea unei metode din clasa de baz redefinite n clasele derivate, se face prin una din
modalitile:
Diferenele de semntur ale metodei redefinite;
Prin legtura cu obiectul asupra cruia se aplic metoda (vezi apelurile metodei arat pentru obiectele
u, v1, v2, w);
Prezena operatorului de rezoluie (de exemplu, dac pentru obiectul w se dorete apelarea metodei arat
din clasa B, apelul va acea forma: w.A::arat(); ).
Un pointer ctre o clas de baz poate primi ca valoare adresa unui obiect dintr-o clas derivat (figura
12.9.). n aceast situaie, se apeleaz metoda din clasa pointerilor, i nu din clasa obiectului spre care
pointeaz pointerul.
Pentru exemplificare, vom considera ierarhia de clase (A, B, C, D) ulterioar, i programul de test:
void main()
{
A u(10), *PA;
// Constructor A 10
B v1(9, 7), *PB; // Constructor A 9
Constructor B 7
- ptr. v1
C v2(8,12), *PC; // Constructor A 8
Constructor C 12
- ptr. v2
D w(31, 9, 14, 35), *PD;
// Constructor A 31
Constructor B 9
PA=&u; PA->arat();
PA=&v1; PA->arat();
PB=&v1; PB->arat();
PA=&w; PB=&w; PD=&w;
u.arat();
PA->arat();
PB->arat();
PD->arat();
}
// Constructor C 14
Constructor D 35
// Se selecteaz metoda arat din clasa A A.a=10
// Se selecteaz metoda arat din clasa A A.a=9
// Se selecteaz metoda arat din clasa B B.b=7
// Apelul metodei arat ptr. obiectul curent, clasa A
A.a=31
// Se selecteaz metoda arat din clasa A
A.a=31
// Se selecteaz metoda arat din clasa B
B.b=9
// Se selecteaz metoda arat din clasa D
D.d=35
u
Aa cum se observ din exemplu,
pa, pb, pc i pd sunt pointeri de
tipurile A, B, C, respectiv D:
pa
a=10
A.a=10
v1
n urma atribuirii
pa=&v1;
pointerul pa (de tip A) va conine
adresa obiectului v1 (de tip B).
Apelul metodei arat redefinite
n clasa derivat B
pa->arat();
a=9
pb
b=7
B.b=7
sau:
B v1(9, 7)
v2
pc
a=8
c=12
C.c=12
sau:
C v2(8, 12)
w
a=31
pd
b=9
c=14
D.d=35
sau:
D w(31,9,14,35)
d=35
198
CAPITOLUL 12
n toate cazurile prezentate anterior, identificarea metodei redefinite se realizeaz n faza de compilare. Este
vorba de o legare inial, "early binding", n care toate informaiile necesare selectrii metodei sunt
prezentate din timp i pot fi utilizate din faza de compilare.
// . . . .
};
class B : virtual public A {
public:
virtual void arat();
//n loc de void arat()
// . . . .
};
class C : virtual public A {
public:
virtual void arat();
//n loc de void arat()
// . . . .
};
class B : public B, public C{
public:
virtual void arat();
//n loc de void arat()
// . . . .
};
CAPITOLUL 12
PA=&u; PA->arat();
PA=&v1; PA->arat();
PB=&v1; PB->arat();
PA=&w; PB=&w; PD=&w;
u.arat();
PA->arat();
PB->arat();
PD->arat();
}
// Constructor C 14
Constructor D 35
// Se selecteaz metoda arat din clasa A
// Se selecteaz metoda arat din clasa B
// Se selecteaz metoda arat din clasa B
A.a=10
B.b=7
B.b=7
A.a=10
D.d=35
D.d=35
D.d=35
Observaie:
1. Deoarece metoda arat este virtual, s-a selectat metoda pentru clasa obiectului spre care pointeaz
pointerul.
2. Dac n clasa de baz se declar o metod virtual, n clasele derivate metodele cu aceeai semnatur
vor fi considerate implicit virtuale (chiar dac ele nu sunt declarate, explicit, virtuale).
n cazul unei funcii declarate virtual n clasa de baz i redefinite n clasa derivat, redefinirea metodei n
clasa derivat are prioritate fa de definirea ei din clasa de baz. Astfel, o funcie virtual declarat n clasa
de baz actioneaz ca un substitut pentru pstrarea datelor care specific o clas general de aciuni i
declar forma interfeei. La prima vedere, redefinirea unei funcii virtuale ntr-o clas derivat pare similar
cu suprancrcarea unei funciei obinuite. Totui, nu este aa, deoarece prototipul unei metode virtuale
redefinite trebuie s coincid cu cel specificat n clasa de baz. n cazul suprancrcrii unei funcii normale,
caracteristicile prototipurilor trebuie s difere (prin tipul returnat, numrul i/sau tipul parametrilor).
Exerciiu: Fie ierahia de clase din figura 12.10. Metoda virtual virt_f , din clasa baz, este redefinit n
clasele derivate.
#include <iostream.h>
class baza{
baz
public:
baz()
{cout<<"Constructor baz\n";}
derivat1
derivat2
~baz()
{cout<<"Destructor baz\n";}
virtual void virt_f()
{cout<<"Metoda virt_f() din baz\n";}
derivat1a
derivat2a
};
class derivat1: public baza{
Figura 12.10. Ierarhie de clase
public:
derivat1():baza()
{cout<<"Constructor derivat1\n";}
~derivat1()
{cout<<"Destructor derivat1\n";}
virtual void virt_f()
{cout<<"Metoda virt_f() din derivat1\n";}
};
class derivat2: public baza{
public:
derivat2():baza()
{cout<<"Constructor derivat2\n";}
~derivat2()
{cout<<"Destructor derivat2\n";}
virtual void virt_f()
{cout<<"Metoda virt_f() din derivat2\n";}
};
class derivat1a: public derivat1{
public:
derivat1a():derivat1()
200
CAPITOLUL 12
{cout<<"Constructor derivat1a\n";}
~derivat1a()
{cout<<"Destructor derivat1a\n";}
virtual void virt_f()
{cout<<"Metoda virt_f() din derivat1a\n";}
};
class derivat2a: public derivat2{
public:
derivat2a():derivat2()
{cout<<"Constructor derivat2a\n";}
~derivat2a()
{cout<<"Destructor derivat2a\n";}
virtual void virt_f()
{cout<<"Metoda virt_f() din derivat2a\n";}
};
void main()
{
baza *p;
//Constructor baz
baza b;
//Constructor baz
derivat1 d1;
// Constructor baz
Constructor derivat1
derivat2 d2;
// Constructor baz
Constructor derivat2
derivat1a d1a;
// Constructor baz
Constructor derivat1
derivat2a d2a;
// Constructor baz
Constructor derivat2
p=&b; p->virt_f();
// Metoda virt_f() din baz
p=&d1;p->virt_f();
// Metoda virt_f() din derivat1
p=&d2;p->virt_f();
// Metoda virt_f() din derivat2
p=&d1a;p->virt_f();
// Metoda virt_f() din derivat1a
p=&d2a;p->virt_f();
// Metoda virt_f() din derivat2a
}
// Destructor derivat2a
// Destructor derivat1a
// Destructor derivat2
// Destructor derivat1
// Destructor baz
Destructor derivat2
Destructor derivat1
Destructor baz
Destructor baz
Constructor derivat1a
Constructor derivat2a
Destructor baz
Destructor baz
(pentru d2a)
(pentru d1a)
(pentru d2)
(pentru d1)
(pentru b)
Exerciu: Fie ierarhia de clase din figura 12.11. Se prezint o modalitate de lucru cu un tablou eterogen, cu
5 elemente, care conine pointeri att spre clasa baza, ct i spre clasele derivat1 i derivat2.
Pentru a putea trata n mod uniform cele trei tipuri de obiecte, s-a creat clasa lista_eterogena.
Aceasta are ca dat membru pointerul la tipul baza i metoda afis (virtual, redefinit n clasele
derivate).
#include <iostream.h>
#include <conio.h>
class baza{
protected:
int val;
public:
baza()
{cout<<"Constructor baza\n";}
~baza()
{cout<<"Destructor baza\n";}
void set_val(int a)
{val=a;}
virtual void afis()
{cout<<"Element baza="<<val<<"\n";}
};
class derivat1: public baza{
public:
derivat1():baza()
{cout<<"Constructor derivat1\n";}
201
baza
derivat1
derivat2
Figura 12.11.
CAPITOLUL 12
~derivat1()
{cout<<"Destructor derivat1\n";}
void afis()
{cout<<"Element derivat1="<<val<<"\n";}
};
class derivat2: public baza{
public:
derivat2():baza()
{cout<<"Constructor derivat2\n";}
~derivat2()
{cout<<"Destructor derivat2\n";}
void afis()
{cout<<"Element derivat2="<<val<<"\n";}
};
class lista_eterogena {
baza *p;
public:
void set_l(baza *pp)
{p=pp;}
void afis()
{p->afis();}
};
void main()
{
clrscr();
baza B[3]; //Constructor baza
Constructor baza
// (pentru elementele tabloului B, de tip baza
Constructor baza
//L[3].set_l(B+1);
//L[4].set_l(&B[2]);
L[4].set_l(B+2);
for (int i=0; i<5; i++)
/*Element baza=10
Element baza=100
L[i].afis();
Element derivat1=444
Element baza=1000*/
Element derivat2=555
n cazul unei ierarhii de clase i a unei metode virtuale a clasei de baz, toate clasele derivate care motenesc
aceast metod i nu o redefinesc, o motenesc ntocmai. Pentru aceeai metod motenit i redefinit n
clasele derivate, selecia se realizeaz n momentul executrii programului (legarea trzie).
Funciile virtuale nu pot fi metode statice ale clasei din care fac parte.
Funciile virtuale nu pot fi funcii prietene sau constructori, dar pot fi destructori. Destructorii virtuali sunt
utili n situaiile n care se dorete distrugerea uniform a unor masive de date eterogene.
Metode virtuale pure
n unele situaii, o clas de baz (din care se deriveaz alte clase) a unei ierarhii, poate fi att de general,
astfel nct unele metode nu pot fi descrise la acest nivel (att de abstract), ci doar n clasele derivate. Aceste
metode se numesc funcii pure . Metodele virtuale pure sunt metode care se declar, nu se definesc la acest
nivel de abstractizare. O metod virtual pur trebuie s fie prezent n orice clas derivat.
Exemple:
class baz{
public:
virtual void virt_f()=0; };
202
CAPITOLUL 12
Crearea ierahiilor de clase
class vieuitoare {
public:
virtual void nutriie()=0; }; //metoda nutriie este o metod virtual pur
O clas cu cel puin o metod virtual pur se numete clas abstract (clasa vieuitoare este abstract
i, ca urmare, nu poate fi instaniat).
NTREBRI I EXERCIII
Chestiuni teoretice
1. Ce este o clas derivat i ce caracteristici
are?
2. Funciile prietene pot fi funcii virtuale?
3. Destructorii se motenesc?
4. Ce este o clas virtual i n ce situaii este
util?
5. Ce este o metod virtual pur i cum se
declar aceasta?
6. Explicai ce nseamn legarea iniial (early
binding).
Chestiuni practice
1. S se implementeze ierarhia de clase din figura 12.12., cu
membrii pe care i considerai necesari.
2. Concepei o ierarhie de clase a figurilor geometrice.
Ca date membre pot fi considerate poziia, dimensiunile
i atributele de desenare (culoare, tip linie). Metodele
vor permite operaii de afiare, deplasare, tergere,
modificarea atributelor figurii. Clasa de baz va avea
proprietile generale ale oricrei figuri: coordonatele
pe ecran i vizibilitate.
3. Din clasa matrice, s se deriveze clasa c_matrice, care
reprezint o matrice de compleci.
persoana
student
angajat
student
bursier
bugetar
(cu salariul
de baz fix)
muncitor
(salariu n acord
global: nr_ore*
tarif_or)
Figura 12.12.
203
CAPITOLUL 12
204