Sunteți pe pagina 1din 5

Lab 9 P2 Polimorfism

Cuprins
1. 2. 3. 4. 5. Polimorfismul ........................................................................................................................................ 1 Funcii virtuale ...................................................................................................................................... 2 Tabela virtual (virtual table) ................................................................................................................ 4 Destructor virtual .................................................................................................................................. 4 Exerciii .................................................................................................................................................. 5

1. Polimorfismul
Polimorfismul reprezint capacitatea unui obiect de tip A de a exista i de a fi utilizat precum un obiect de tipul B. Considernd exemplul claselor StudentAC si PersoanaAC, unde clasa StudentAC este o clasa derivat din clasa PersoanaAC, polimorfismul reprezint modul de utilizare a unui obiect StudentAC n locul unui obiect PersoanaAC pentru un obiect de tipul PersoanaAC. Altfel spus, un obiect de tipul unei clase derivate este compatibil ca pointer cu un obiect de tipul clasei de baz. Considernd implementrile precedente ale claselor PersoanaAC si StudentAC, un exemplu de utilizare a polimorfismului este:

StudentAC *s3 = new StudentAC ("1234567890122", "Ion", "Vaslui",2,10); StudentAC s4("7734567890122","Vasile","Neamt",3,7); PersoanaAC *ps2 = s3; PersoanaAC *ps3 = &s4; PersoanaAC &ps=s4; ps2->afisareProfil(); ps3->afisareProfil(); delete s3;
Consideram codul urmator:

PersoanaAC *ps5 = new StudentAC ("9999567890122", "Pavel", "Iasi",1,10); ps5->afisareProfil();


La rularea acestuia, se va afia pe ecran

Nume: Pavel CNP: 9999567890122 Adresa: Iasi

Observam c pentru obiectul ps5 nu se apeleaz funcia afiare profil din StudentAC, ci se apeleaz funcia afisareProfil din clasa PersoanaAC. Pentru a corecta acest lucru, se introduce conceptul de funcii virtuale.

2. Funcii virtuale
O funcie virtual este un tip special de funcie care permite apelarea funciei din clasa cea mai derivat cu acelai prototip. O funcie a unei clase ce poate fi redefinit ntr-o clas derivat este o funcie virtual. Pentru a declara o funcie virtual, se folosete cuvntul cheie virtual naintea declarrii funciei. Pentru a putea apela funcia afisareProfil din clasa StudentAC pentru obiectul ps5, se va declara funcia afisareProfil din clasa de baza virtual:

class PersoanaAC { ... virtual void afisareProfil(); ... }; ... PersoanaAC *ps5 = new StudentAC ("9999567890122","Pavel", "Iasi",1,10); ps5->afisareProfil();

La rularea codului de mai sus, se va afia:

Nume: Pavel CNP: 9999567890122 Adresa: Iasi An studiu: 1 Nota P2: 10


Observaii: ps5 este o adres ctre clasa de baz PersoanaAC a unui obiect derivat StudentAC cnd este evaluat funcia afiareProfil(), n mod normal ar fi apelat funcia din clasa de baz deoarece funcia PersoanaAC::afisareProfil() este virtual, compilatorul caut s vad dac exist o funcie cu acelai prototip n clasa derivat StudentAC daca aceasta funcie exista, va fi apelata in locul funciei din clasa de baza Altfel spus, pentru c ps5 este adresa clasei de baz a unui obiect StudentAC, compilatorul va verifica fiecare membru motenit i va folosi varianta cea mai derivat pentru o funcie apelat. Funcia redefinit trebuie s aib aceiai parametri i acelai tip de return ca i funcia original din clasa de baz.

Observaii: Pentru o clas ce nu are nici o alt clas derivat din ea, folosirea funciilor virtuale nu este necesar! Se recomand a nu se face toate funciile virtuale pentru a spori claritatea codului scris! Folosirea funciilor virtuale presupune existena claselor derivate si a polimorfismului! O funcie definit virtual n clasa de baz, va rmne virtual n tot arborele ierarhic a acelei clase, indiferent cte niveluri are derivarea. n acest sens, utilizam exemplul urmtor:

class A { public: virtual void f() { cout << "Class A" << endl; } }; class B: public A { public: void f(int x) { cout << "Class B" << endl; } }; class C: public B { public: void f() { cout << "Class C" << endl; } }; int main() { B b; C c; A *pa1 = &b; A &pa2 = c; pa1->f(); pa2.f(); }

La rularea acestui exemplu, se va afia:

Class A Class C
In acest exemplu, Clasa B motenete clasa A, iar clasa C motenete clasa B. Funcia B::f nu este virtual i are prototipul diferit fa de funcia A::f. Deoarece C motenete i clasa A, funcia A::f() este virtual i pentru clasa C. Din acest motiv, la apelarea pa2.f() se apeleaz C::f() ca funcia cea mai derivat pentru un obiect de tipul C.

3. Tabela virtual (virtual table)


Tabela virtual conine pointeri ctre funcii virtuale. Ea este creat pentru fiecare clas ce conine funcii membre virtuale sau suprascrie funcii virtuale. Pentru o anumit clas exist o singur tabel virtual. Exist clase pentru care tabela virtuala nu este creat. Cnd un obiect este creat, se adaug un membru ascuns, un pointer ctre aceast tabel virtual. Compilatorul genereaz automat codul n constructori pentru iniializarea pointerului ctre aceast tabel. Tabela se acceseaz n momentul cnd se execut o funcie virtual, pentru a asigura o eficien sporit programului. Tabela poate fi consultat cu ajutorul debug-ului: De exemplu, pentru un obiect ps3 declarat n modul urmtor:

StudentAC s4("7734567890122","Vasile","Neamt",3,7); PersoanaAC *ps3 = &s4;


La efectuarea funciei watch pe acest obiect, se poate observa tabela sa virtuala ce conine pointeri spre funciile ce vor fi apelate pentru orice funcie accesibil obiectului ps3:

4. Destructor virtual
Destructorii claselor de baz trebuie declarai virtuali pentru a asigura apelarea destructorilor din clasele derivate. n caz contrar exist pericolul de a nu dealoca toat memoria utilizat. n cazul destructorilor, se apeleaz toi destructorii dinspre clasa derivat ctre clasa de baz (n ordinea invers a apelrii constructorilor).

5. Exerciii
Scriei un program ce conine o clasa de baz Figura si dou clase derivate din aceasta Cerc i Dreptunghi. Clasa Figura va avea un membru culoare de tip string metodele Perimetru() si Afisare() Clasa Patrat va avea: ca membri: o coordonatele x, y ale vrfului din stnga-jos al ptratului (de tip ntreg) o latura reprezentnd lungimea laturii ptratului (de tip double) Metodele Perimetru() i Afisare() Clasa Cerc va avea: Ca membri: o Coordonatele x, y ale centrului cercului (de tip ntreg) o Raza r (de tip ntreg) Metodele Perimetru() i Afisare() Cerine: o Completai clasele descrise mai sus cu constructorii necesari pentru a putea citi de la tastatur toi parametrii obiectelor ce vor fi instaniate din fiecare clas. o Completai clasele cu funciile Perimetru i Afisare. o Creai un tablou de pointeri la clasa Figura care s conin: o 2 obiecte de tip Cerc o 2 obiecte de tip Patrat o Utiliznd numai obiectele din acest tablou, testai metodele din clasele scrise. o Determinai obiectul cu aria maxima dintre elementele tabloului.

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