poo 6lucrari

34
Florin Brleanu Programare orientată pe obiecte pentru ncepători 6 lucrări practice n C++ Vrei să nveţi C++, Java sau C#? Trebuie mai nti să ştii...

Upload: meteaadrian

Post on 17-Jan-2016

77 views

Category:

Documents


6 download

DESCRIPTION

Programare orientata pe obiecte

TRANSCRIPT

Page 1: POO 6lucrari

Florin Bîrleanu

Programare orientată pe obiecte

pentru începători

6 lucrări practice în C++

Vrei să înveţi C++, Java sau C#? Trebuie mai întâi să ştii...

Page 2: POO 6lucrari

Florin Bîrleanu � Programare orientată pe obiecte pentru începători http://igotopia.ro

2

Cuprins:

1. Clase şi obiecte 3 2. Constructori şi destructori 10 3. Încapsulare şi compunere 14 4. Suprascrierea metodelor şi operatorilor 19 5. Moştenire 23 6. Polimorfism 28

Page 3: POO 6lucrari

Florin Bîrleanu � Programare orientată pe obiecte pentru începători http://igotopia.ro

3

Lucrarea nr. 1

Clase si obiecte

1. Scopul lucrarii

Lucrarea isi propune sa faca o introducere in programarea orientata pe obiecte. Vor fi tratate in special conceptele esentiale de clasa si obiect. Dupa efectuarea lucrarii vei cunoaste prin ce difera programarea orientata pe obiecte de programarea clasica, procedurala, si vei sti sa declari clase si sa defineasca obiecte din clasele respective.

2. Notiuni teoretice

Trebuie punctat inca de la inceput faptul ca se poate programa si fara a folosi conceptele pe care le introduce programarea orientata pe obiecte. Orice program realizat cu obiecte ar putea fi facut si folosind programarea clasica (procedurala). Caci programarea orientata pe obiecte e doar un mod de a organiza programele, si nu e in mod fundamental diferita de programarea procedurala.

Conceptul fundamental din programarea orientata pe obiecte (POO) il constituie clasa. O clasa este in esenta o structura ce poate contine pe langa variabile, functii. Deci o clasa este o structura ce grupeaza laolalta datele si actiunile legate de un anumit tip de obiecte. Practic, ca si structura (struct, in limbajul C), clasa (class, in limbajul C++) defineste un nou tip de date.

Folosind acest nou tip de date se pot defini, bineinteles, variabile -- care poarta numele de obiecte. Accesarea membrilor unei clase se face, ca si in cazul structurii, folosind operatorul �.� dupa un obiect apartinand clasei respective.

Variabilele sau obiectele continute intr-o clasa poarta numele de date membru (sau campuri), iar functiile continute intr-o clasa poarta numele de functii membru (sau metode). Atat campurile, cat si metodele, pot sa fie sau nu accesibile din exteriorul clasei. Specificarea membrilor accesibili din afara ai unei clase se face folosind specificatorul de acces public, in vreme ce pentru membrii inaccesibili trebuie folosit specificatorul private.

In mod implicit (deci in cazul in care nu se scrie niciun specificator de acces) toti membrii clasei sunt inaccesibili (ceea ce inseamna ca specificatorul de acces private este implicit). Motivul pentru acest comportament este acela ca scopul claselor este de a grupa laolalta (asa cum am spus) toate datele si actiunile necesare pentru a opera cu un anumit tip (sau clasa) de obiecte. Iar gruparea aceasta se face in scopul simplificarii muncii programatorului prin divizarea aplicatiei software in clase de obiecte care sunt bine separate unele de altele si pot comunica intre ele doar in moduri bine stabilite (fara ca un obiect dintr-o clasa sa trebuiasca sa

Page 4: POO 6lucrari

Florin Bîrleanu � Programare orientată pe obiecte pentru începători http://igotopia.ro

4

cunoasca detalii interne legate de implementarea unui obiect dintr-o alta clasa). Asadar, detaliile interne ale unei clase trebuie tinute �secrete� (private) fata de

utilizatorii clasei respective, lasand vizibile (public) doar acele actiuni la care trebuie sa poata raspunde obiectele acelei clase in vederea operarii cu ele. Este o practica buna, asadar, ca toate datele membre ale unei clase sa fie private, in vreme ce doar o parte dintre metode sa fie public.

Sintaxa pentru definirea unei clase in limbajul C++ este urmatoarea: class NumeClasa { private: // date

// (si, eventual, unele metode) � int nr; public: // metode publice

// (actiuni ce pot fi realizate de catre obiectele clasei, sau asupra lor) � void Scrie(int val); int Citeste();

}; void NumeClasa::Scrie(int val) { nr = val; } int NumeClasa::Citeste() { return nr; } �

Odata declarata o clasa, ea poate fi utilizata pentru a defini obiecte in mod similar utilizarii unui tip de date deja existent: NumeClasa numeObiect; Crearea unui obiect apartinand unei clase mai poarta numele de instantiere a clasei respective. Ulterior definirii lui, obiectul numeObiect poate fi folosit pentru a apela metodele publice. De exemplu, i se poate seta valoarea interna scriind:

Page 5: POO 6lucrari

Florin Bîrleanu � Programare orientată pe obiecte pentru începători http://igotopia.ro

5

numeObiect.Scrie(7);

Trebuie mentionat ca incercarea de a accesa un camp sau o metoda ce au fost declarate cu private genereaza o eroare la compilarea programului.

3. Desfasurarea lucrarii

Exemplele si exercitiile din aceasta lucrare vor fi realizate folosind mediul de dezvoltare Microsoft Visual C++. La crearea proiectului se va alege tipul �Win32

Console Application�. 3.1. Exemplu

Se va realiza urmatorul exemplu ce isi propune sa arate comparativ realizarea unui program simplu in programarea clasica si in programarea orientata pe obiecte. Programul isi propune sa afiseze pe ecran (in mod text) o tabla de X&O.

Rezultatul dorit este de genul urmator:

+-+-+-+ | | |X| +-+-+-+ | | | | +-+-+-+ |X|O| | +-+-+-+ In fiecare dintre cele 9 pozitii de pe tabla se va putea gasi una dintre urmatoarele 3 �piese�: - nimic (spatiu) - piesa �X� (X) - piesa �O� (O). 3.1.1. Solutia clasica

Pentru fiecare pozitie de pe tabla vom folosi o valoare de tip numar intreg (int), cu urmatoarea semnificatie: 0 → � � (spatiu) 1 → �X� 2 → �O�. Prin urmare, cel mai natural e sa folosim o matrice de 3x3 elemente de tip numar intreg.

Page 6: POO 6lucrari

Florin Bîrleanu � Programare orientată pe obiecte pentru începători http://igotopia.ro

6

Programul va avea urmatoarea structura: → Defineste tabla: int t[3][3]; → Pune piese pe tabla: e.g. t[0][0] = 0; t[0][2] = 1; � → Afiseaza tabla: void AfiseazaTabla(int t[3][3]).

Codul sursa al programului e prezentat in contiuare:

#include <stdio.h> #include <conio.h>

void AfiseazaTabla(int t[3][3]) { int l; int c; for (l=0; l<3; l++) { printf(�+-+-+-+\n�); for (c=0; c<3; c++) { printf(�|�); if (t[l][c] == 0) printf(� �); else if (t[l][c] == 1) printf(�X�); else if (t[l][c] == 2) printf(�O�); } printf(�|\n�); } printf(�+-+-+-+\n�); } void main(void) { // Defineste tabla: int t[3][3]; // Pune piese pe tabla: t[0][0] = 0; t[0][1] = 0; t[0][2] = 1; t[1][0] = 0; t[1][1] = 0; t[1][2] = 0; t[2][0] = 1; t[2][1] = 2; t[2][2] = 0; // Afiseaza tabla: AfiseazaTabla(t); getch(); // asteapta... }

3.1.2. Solutia POO

Page 7: POO 6lucrari

Florin Bîrleanu � Programare orientată pe obiecte pentru începători http://igotopia.ro

7

Daca ne uitam cu atentie peste structura programului (care contine, in esenta,

trei actiuni: (1) defineste tabla, (2) pune piesele pe tabla si (3) afiseaza tabla), observam ca intregul program consta in manipularea obiectului tabla. Asa ca am putea grupa laolalta datele si actiunile privind tabla de joc, construind clasa TablaDeJoc: class TablaDeJoc { private: int t[3][3]; public: void Afiseaza(); void PunePiesa(int l, int c, int p); }; void TablaDeJoc::Afiseaza()

{ int l; int c; for (l=0; l<3; l++) { printf(�+-+-+-+\n�); for (c=0; c<3; c++) { printf(�|�); if (t[l][c] == 0) printf(� �); else if (t[l][c] == 1) printf(�X�); else if (t[l][c] == 2) printf(�O�); } printf(�|\n�); } printf(�+-+-+-+\n�); } void TablaDeJoc::PunePiesa(int l, int c, int p) { t[l][c] = p; }

Asa cum se vede, clasa TablaDeJoc contine ca date matricea t (ce va

memora continutul fiecarei pozitii de pe tabla), iar ca metode Afiseaza() si PunePiesa(). Ulterior declararii structurii clasei am definit aceste metode la fel cum am defini niste functii obisnuite, doar ca numele lor le-am precedat de numele clasei (TablaDeJoc) si de operatorul �::� (care specifica faptul ca ne referim la un

Page 8: POO 6lucrari

Florin Bîrleanu � Programare orientată pe obiecte pentru începători http://igotopia.ro

8

identificator definit in cadrul clasei respective).

Pentru a scrie un program rulabil este necesar sa adaugam functia �main�

(plus eventualele fisiere antet ce declara functii sau alte clase pe care le folosim): #include <stdio.h> #include <conio.h> class TablaDeJoc { ... }; � // ← definirea metodelor clasei TablaDeJoc void main(void) { TablaDeJoc tabla; tabla.PunePiesa(0, 0, 0); tabla.PunePiesa(0, 1, 0); tabla.PunePiesa(0, 2, 1); tabla.PunePiesa(1, 0, 0); tabla.PunePiesa(1, 1, 0); tabla.PunePiesa(1, 2, 0); tabla.PunePiesa(2, 0, 1); tabla.PunePiesa(2, 1, 2); tabla.PunePiesa(2, 2, 0); tabla.Afiseaza(); getch(); }

Comparand programul acesta cu cel prezentat anterior se poate observa un plus de claritate si de transparenta privind detaliile interne ale tablei. Acum matricea t nu mai este definita in program, si nici nu este accesibila din afara clasei TablaDeJoc. De asemenea, nu este necesara transmiterea ei ca parametru metodelor Afiseaza() si PunePiesa() (caci fiind membre ale clasei TablaDeJoc ele au acces direct la toti membrii clasei (inclusiv la cei declarati private)).

Un alt avantaj il constituie faptul ca daca ulterior dorim sa utilizam o alta structura de date (eventual pentru a optimiza memoria utilizata) pentru a memora continutul pozitiilor de pe tabla, vom putea face acest lucru fara sa afectam in vreun fel programele care folosesc obiecte de tipul clasei TablaDeJoc. Aceste programe vor ramane neschimbate ca forma, iar o simpla recompilare a lor va fi suficienta pentru ca ele sa beneficieze de plusurile aduse de noua versiune a clasei.

Bineinteles, insa, ca exista si unele dezavantaje ale solutiei POO fata de solutia clasica. Este evident ca in cazul programului oferit aici ca exemplu solutia POO implica mai multa munca de codare, programul total fiind putin mai lung. Partea buna este, insa, aceea ca munca poate fi mai bine impartita intre programatori in cazul solutiei POO (unii putand lucra la construirea claselor necesare programului, iar altii la programul propriu-zis). Odata realizata si testata o clasa, ea devine o entitate de sine statatoare ce inglobeaza tot ce ii este necesar pentru a putea oferi functionalitatea dorita, iar utilizarea ei va fi foarte facila (necesitand doar instantierea ei si apoi utilizarea membrilor publici pe care ii ofera). Cu alte cuvinte, o clasa este

Page 9: POO 6lucrari

Florin Bîrleanu � Programare orientată pe obiecte pentru începători http://igotopia.ro

9

ca o cutie neagra ce stie sa execute un numar limitat de actiuni ca raspuns la un set finit de mesaje. 3.2. Exercitii (1) Sa se scrie si sa se ruleze cele doua programe folosind Visual C++. Notati observatiile. (2) Sa se modifice ambele programe astfel incat tabla sa nu mai fie de 3x3 pozitii, ci de 4x4. Ce observati? (3) Sa se modifice ambele programe rezultate la punctul (2) astfel incat variabila t sa nu mai fie denumita t, ci x. Ce observati? (4) Sa se adauge in clasa TablaDeJoc o metoda numita CePiesa(), care sa returneze piesa de pe o pozitie specificata prin intermediul parametrilor. Prin ce ar fi diferit aceasta metoda daca ar fi fost implementata ca functie in varianta clasica, si nu ca metoda intr-o clasa? (5) Sa se foloseasca in program aceasta metoda astfel: la finalul programului sa se citeasca de la tastatura doua numere (linia si coloana); apoi sa se afiseze pe ecran ce contine tabla la pozitia specificata. (6) Sa se separe codul sursa al programului de la punctul (5) in mai multa fisiere, astfel incat clasa TablaDeJoc si functia main sa fie definite in fisiere diferite. La ce este utila aceasta activitate?

Bibliografie [1] Peter Muller. Introduction to Object-Oriented Programming using C++. http://www.tiem.utk.edu/~gross/c++man/ [2] Object-Oriented Programming in C++. http://www.ntu.edu.sg/home/ehchua/programming/cpp/cp3_OOP.html [3] http://www.cplusplus.com/doc/tutorial/classes/

Page 10: POO 6lucrari

Florin Bîrleanu � Programare orientată pe obiecte pentru începători http://igotopia.ro

10

Lucrarea nr. 2

Constructori si destructori

1. Scopul lucrarii

In aceasta lucrare vei invata ce sunt constructorii si destructorii pentru o clasa, la ce sunt utili si cum poti fi declarati si folositi in programe.

2. Notiuni teoretice

Constructorii si destructorii claselor sunt metode speciale ce se apeleaza in mod automat: - la crearea unui obiect ← constructorul - la distrugerea unui obiect ← destructorul.

Pentru a intelege mai bine rolul si utilizarea constructorilor a a destructorilor, este necesar sa revenim la modul cum sunt construite si distruse variabilele obisnuite (care nu sunt obiecte).

O variabila normala (care nu e pointer) este creata in momentul definirii ei in program, si este distrusa la iesirea din blocul ({...}) in care a fost definita: { � int x; // ← creare �obiect� x ... } // ← distrugere �obiect� x

Pe de alta parte, o �variabila� (sau spatiu de memorie) alocata prin intermediul

unui pointer (folosind operatorul new in C++) continua sa existe pana in momentul in care este distrusa prin utilizarea operatorului delete (in C++):

int *px; px = new int; // ← creare �obiect� (*px) � delete px; // ← distrugere �obiect� (*px)

Constructorul (sau constructorii) si destructorul unei clase se definesc ca

metode ce au acelasi nume ca al clasei (cu exceptia faptului ca destructorul mai are o �~� imediat inaintea numelui) si nu returneaza nimic (nici macar �void�): class NumeClasa {

Page 11: POO 6lucrari

Florin Bîrleanu � Programare orientată pe obiecte pentru începători http://igotopia.ro

11

private: � public: NumeClasa(); // ← constructor fara parametri NumeClasa(int parametru); // ← constructor un parametru � ~NumeClasa(); // ← destructor ... }; NumeClasa::NumeClasa() { ... } NumeClasa::NumeClasa(int parametru) { � } NumeClasa::~NumeClasa() { ... } ...

Pentru a vedea mai clar utilitatea constructorului si a destructorului ne putem gandi ca exemplu sugestiv la un obiect de tip MeniuContextual (care apare atunci cand utilizatorul face click dreapta pe diverse elemente din interfata grafica a unei aplicatii). Meniul care apare pe ecran (ca si functionalitatea aferenta lui) poate fi diferit in functie de elementul din interfata pe care s-a facut click dreapta. Cum nu e optim sa ocupam in permanenta memoria sistemului cu toate meniurile contextuale posibile, le putem construi si distruge dinamic (cu operatorii new si delete). Astfel, in constructor putem face (pe langa initializarile datelor interne) afisarea meniului pe ecran, iar in destructor putem face stergerea lui de pe ecran.

3. Desfasurarea lucrarii

Exemplele si exercitiile din aceasta lucrare vor fi realizate folosind mediul de dezvoltare Microsoft Visual C++. La crearea proiectului se va alege tipul �Win32

Console Application�. 3.1. Exemplu

Page 12: POO 6lucrari

Florin Bîrleanu � Programare orientată pe obiecte pentru începători http://igotopia.ro

12

Pentru a ilustra modul in care se definesc si se folosesc constructorii pentru o clasa vom relua exemplul discutat in lucrarea trecuta (clasa TablaDeJoc). Ii vom adauga un constructor si un destructor astfel: #include <stdio.h> class TablaDeJoc { private: int t[3][3]; // ← camp public: TablaDeJoc(); // ← constructor implicit (i.e. fara parametri) ~TablaDeJoc(); // ← destructor void Afiseaza(); // ← metoda void PunePiesa(int l, int c, int p); // ← metoda }; TablaDeJoc::TablaDeJoc() { int l, c; for (l=0; l<=2; l++) for (c=0; c<=2; c++) t[l][c] = 0; } TablaDeJoc::~TablaDeJoc() { printf(�Bye! :-)\n�); } ...

Constructorul TablaDeJoc::TablaDeJoc() se va apela in program automat in momentul instantierii clasei TablaDeJoc (deci atunci cand definim obiectul tabla (← a

se revedea programul din lucrarea trecuta)): TablaDeJoc tabla;

Desi o clasa poata avea un singur destructor, ea poate avea mai multi constructori. Diferentierea intre ei compilatorul o va face (la fel ca in cazul metodelor si al functiilor obisnuite) prin intermediul numarului si tipului parametrilor. Sa vedem, de exemplu, cum am defini un constructor pentru clasa TablaDeJoc care in loc sa initializeze elementele tablei cu valoarea 0, sa le initializeze cu o valoare primita ca parametru: TablaDeJoc::TablaDeJoc(int p)

Page 13: POO 6lucrari

Florin Bîrleanu � Programare orientată pe obiecte pentru începători http://igotopia.ro

13

{ int l, c; for (l=0; l<=2; l++) for (c=0; c<=2; c++) t[l][c] = p; } Pentru a apela acest constructor va trebui ca in program sa modificam putin sintaxa pentru instantierea clasei, construind obiectul tabla astfel: TablaDeJoc tabla(1); // ← elementele tablei vor fi toate �X� 3.2. Exercitii (1) In programul din lucrarea trecuta sa se apeleze tabla.Afiseaza() imediat dupa instantierea clasei TablaDeJoc. Ce apare pe ecran? (2) Sa se adauge constructorul implicit si sa se repete pasul anterior. Ce s-a modificat? (3) Sa se implementeze si constructorul cu parametru discutat anterior si sa se testeze in program. (4) Sa se adauge si destructorul clasei TablaDeJoc si sa se scrie un program de test care sa ilustreze apelarea lui.

Bibliografie [1] Constructors and destructors in C++. http://www.cprogramming.com/tutorial/constructor_destructor_ordering.html [2] Overview of contructors and destructors (C++ only). http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8a.doc%2Flanguage%2Fref%2Fcplr374.htm [3] http://www.tutorialspoint.com/cplusplus/cpp_constructor_destructor.htm

Page 14: POO 6lucrari

Florin Bîrleanu � Programare orientată pe obiecte pentru începători http://igotopia.ro

14

Lucrarea nr. 3

Incapsulare si compunere

1. Scopul lucrarii

Scopul acestei lucrari il constituie intelegerea a doua concepe foarte importante pe care este construita ideea programarii orientate pe obiecte. Voi discuta si ilustra incapsularea si compunerea claselor.

2. Notiuni teoretice

Incapsularea e un concept de baza in programarea orientata pe obiecte. Ea consta in gruparea laolalta (cadrul unei clase) a tuturor informatiilor esentiale ce definesc obiectele din acea clasa (si se realizeaza, asa cum am arata in lucrarile trecute, prin intermediul compurilor, metodelor si specificatorilor de acces).

Conceptul de incapsulare e legat si de ascunderea detaliilor interne ale unei clase si lasarea vizibile doar a acelor detalii care sunt absolut necesare pentru operarea cu acea clasa. Pentru a lasa posibilitatea modificarii ulterioare a structurii interne a unei clase (in vederea optimizari sau a extinderii functionalitatii, de exemplu), e necesar ca datele interne ale clasei sa fie invizibile (private), operarea cu ele facandu-se prin intermediul unor metode vizibile (public): class NumeClasa { private: int data; public: � int CitesteData(); void ScrieData(int data); }; � int NumeClasa::CitesteData() { return data; } void NumeClasa::ScrieData(int data) { this->data = data;

Page 15: POO 6lucrari

Florin Bîrleanu � Programare orientată pe obiecte pentru începători http://igotopia.ro

15

}

A se remarca faptul ca in metoda ScrieData() oferita ca exemplu aici am folosit pentru parametrul metodei acelasi nume cu al campului data din cadrul clasei NumeClasa. Pentru ca compilatorul sa poata evita aceasta confuzie am folosit sintaxa this->data, care acceseaza campul data al clasei NumeClasa prin intermediul pointerului implicit this (care este un cuvant cheie in C++ si reprezinta un pointer catre obiectul curent pentru care se apeleaza metoda). (Reamintesc faptul ca operatorul �->� are rolul de a dereferentia o zona de memorie referita printr-un pointer si de a accesa apoi un camp din cadrul structurii continute acolo. Prin urmare, this->data este echivalent cu (*this).data.)

Compunerea este un alt concept de baza in programarea orientata pe obiecte. Ea se refera la faptul ca un obiect poate avea in compozitia sa (adica in cadrul datelor membre) alte obiecte (de diferite tipuri). Aces mod de a construi programe modeleaza aspecte din lumea reala, in care obiectele pot fi construite din imbinarea mai multor alte obiecte mai mici.

3. Desfasurarea lucrarii

Exemplele si exercitiile din aceasta lucrare vor fi realizate folosind mediul de dezvoltare Microsoft Visual C++. La crearea proiectului se va alege tipul �Win32

Console Application�. 3.1. Exemplu 3.1.1. Incapsulare

Un exemplu de incapsulare am vazut in lucrarile trecute. Este vorba de clasa TablaDeJoc, ce incapsuleaza date si actiuni privitoare la o tabla de X&O.

Vom studia aici un alt exemplu: o clasa ce incapsuleaza date si actiuni aferente operarii cu un numar complex.

Reamintesc faptul ca un numar complex este un numar de forma: z = re + i* im (Valorile re si im sunt numere reale, re fiind partea reala si im partea imaginara, iar i este unitatea pe axa valorilor imaginare (fiind egal cu radacina patrata din (-1)).) Prin urmare, pentru a putea opera cu un numar complex trebuie sa memoram doua variabile -- partea imaginara si partea reala. In ceea ce priveste actiunile pe care sa le putem face cu el, ne putem gandi la: - accesarea partii reale si a partii imaginare (scriere/citire valori)

Page 16: POO 6lucrari

Florin Bîrleanu � Programare orientată pe obiecte pentru începători http://igotopia.ro

16

- calculul modulului - calculul unghiului - adunarea cu un alt numar complex - inmultirea cu un alt numar complex - etc.

Prezint in continuare o parte din definirea clasei NrComplex: #include <math.h> class NrComplex { private: double re; // ← partea reala double im; // ← partea imaginara public: // constructori: NrComplex(); // ← constructor implicit NrComplex(double re, double im); // ← constructor // metode de acces: double CitesteRe(); void ScrieRe(double re); double CitestetIm(); voidScrieIm(double im); // metode utilitare: double Modul(); double Unghi(); void Aduna(NrComplex c); void Inmulteste(NrComplex c); ... }; NrComplex::NrComplex() { re = 0; im = 0; } NrComplex::NrComplex(double re, double im) { this->re = re; this->im = im; } double NrComplex::CitesteRe()

Page 17: POO 6lucrari

Florin Bîrleanu � Programare orientată pe obiecte pentru începători http://igotopia.ro

17

{ return re; } double NrComplex::ScrieRe(double re) { this->re = re; } � double NrComplex::Modul() { return sqrt(re*re+im*im); } � void NrComplex::Aduna(NrComplex c) { re += c.re; im += c.im; } �

A se observa ca in metoda Aduna() am accesat campurile re si im ale obiectului c (de tip NrComplex) primit ca parametru direct (folosind operatorul �.�, si

nu metodele de citire CitesteRe() si CitesteIm()). In mod normal acest lucru genereaza o eroare de compilare (caci campurile re si im au fost definite ca fiind private in clasa NrComplex). Totusi, cum metoda Aduna() face parte din clasa NrComplex, ea are acces la elementele te tip private ale clasei (chiar daca acestea apartin altei instante a clasei -- in cazul acesta fiind vorba de obiectul c). 3.1.2. Compunere

Un obiect de tip JocDeXsiO poate avea in compozitia sa obiecte de tip TablaDeJoc (de care am discutat in lucrarile trecute) si de tip Jucator. Un exemplu in acest sens este ilustrat in continuare: class JocDeXsiO { private: TablaDeJoc tabla; Jucator juc1;

Page 18: POO 6lucrari

Florin Bîrleanu � Programare orientată pe obiecte pentru începători http://igotopia.ro

18

Jucatorjuc2; public: JocDeXsiO(); void Initializeaza(); void Joaca(); int RezultatJoc(); }; 3.2. Exercitii (1) Sa se implementeza clasa NrComplex si sa se scrie un program de test. (2) Sa se implementeze clasa Jucator: class Jucator { private: int tip; // 1 ← X; 2 ← O public: Jucator(); void StabilestePiese(int tip); Piesa CitesteMutare(); // ← citeste de la tastatura mutarea

// ca numar de la 1 la 9 }; Piesa reprezinta o structura definita dupa cum urmeaza: struct Piesa { int l; int c; int tip; }; Sa se scrie un program de test pentru clasa Jucator. (3) Sa se implementeze clasa JocDeXsiO si sa se scrie un program de test.

Bibliografie [1] Objects and Encapsulation. http://sfb649.wiwi.hu-berlin.de/fedc_homepage/ xplore/ebooks/html/csa/node110.html

Page 19: POO 6lucrari

Florin Bîrleanu � Programare orientată pe obiecte pentru începători http://igotopia.ro

19

Lucrarea nr. 4

Suprascrierea metodelor si operatorilor

1. Scopul lucrarii

Lucrarea aceasta are ca scop intelegerea rolului si utilizarii notiunii de suprascriere a metodelor. De asemenea, se va studia modul in care operatorii standard ai limbajului C++ pot fi facuti sa poata opera direct cu obiecte de diverse clase.

2. Notiuni teoretice

Suprascrierea se refera in general la utilizarea aceluiasi nume pentru mai multe functii, dar cu liste de parametri diferite. Compilatorul va putea face diferenta intre acele functii pe baza parametrilor pe care ii folosim la apelul functiei in program. Diferentierea intre listele de parametri se face atat dupa numarul parametrilor, cat si dupa tipul lor. De exemplu, functiile void f(); void f(int x); void f(double x); void f(int x, int y); au toate acelasi nume, dar liste de parametri diferite -- deci nu va exista ambiguitate si compilatorul va sti pe care dintre cele patru functii am apelat-o. Deja am aratat intr-o lucrare anterioara un exemplu de suprascriere, si anume suprascrierea constructorilor (o clasa putand avea atat constructor implicit, cat si constructori cu parametri). Orice alta metoda poate fi suprascrisa in mod similar.

Un caz si mai interesant de suprascriere il constituie suprascrierea operatorilor. Aceasta inseamna ca putem defini comportamentul operatorilor standard ai limbajului C++ (operatori ca �+�, �-�, �*�, �/�, etc.) pentru ca acestia sa

poata opera cu obiecte din clase nou construite. De exemplu, putem face ca operatorii aritmetici uzuali sa poata opera direct cu numere complexe (deci cu instante ale clasei NrComplex definita intr-o lucrare anterioara).

Cu alte cuvinte, vom putea scrie in programe instructiuni de genul urmator: NrComplex c1(2, -3); NrComplex c2(1, 2); NrComplex c3; c3 = c1+c2; // ← = 3 - i

Page 20: POO 6lucrari

Florin Bîrleanu � Programare orientată pe obiecte pentru începători http://igotopia.ro

20

Sintaxa pentru a suprascrie un operator este similara sintaxei utilizate pentru definirea unei functii, cu mentiunea ca in loc de numele functiei se va scrie operator urmat de operatorul care se doreste a fi redefinit. De exemplu, pentru suprascrierea operatorului �+� de catre clasa NrComplex va trebui sa introducem in cadrul acesteia

urmatoarea metoda publica: NrComplex operator+ (NrComplex c);

O alta varianta de a redefini functionarea operatorului �+� astfel incat sa poata

opera cu obiecte de tip NrComplex consta in a declara functia operator+ ca fiind functie prietena (friend) a clasei NrComplex. Acest lucru se poate face scriind in clasa NrComplex: friend NrComplex operator+ (NrComplex c1, NrComplex c2); si are rolul de a permite ca in corpul functiei operator+ (pe care il vom defini, bineinteles, in afara corpului clasei NrComplex) sa putem accesa membrii privati re si im ai obiectelor c1 si c2.

3. Desfasurarea lucrarii

Exemplele si exercitiile din aceasta lucrare vor fi realizate folosind mediul de dezvoltare Microsoft Visual C++. La crearea proiectului se va alege tipul �Win32

Console Application�. 3.1. Exemplu 3.1.1. Suprascrierea metodelor

Un exemplu de suprascriere a metodelor in cadrul unei clase este ilustrat in continuare, folosind drept cobai o clasa al carei scop este acela de a afisa pe ecran numere de diverse tipuri: class AfisorDeNumere { public: void Afiseaza(char x); void Afiseaza(int x); void Afiseaza(long x); void Afiseaza(float x); void Afiseaza(double x); }; void AfisorDeNumere::Afiseaza(char x)

Page 21: POO 6lucrari

Florin Bîrleanu � Programare orientată pe obiecte pentru începători http://igotopia.ro

21

{ printf(�%d�, x); } ... void AfisorDeNumere::Afiseaza(float x) { printf(�%f�, x); } � 3.1.2. Suprascrierea operatorilor

Prezint in continuare modalitatea de redefinire a operatorilor �+� si �*� pentru a

putea opera cu obiecte de tip NrComplex: class NrComplex { � public: NrComplex operator+ (NrComplex c); NrComplex operator* (NrComplex c); }; � NrComplex NrComplex::operator+ (NrComplex c) { NrComplex rez(this->re, this->im); rez.re += c.re; rez.im += c.im; return rez; } NrComplex NrComplex::operator* (NrComplex c) { NrComplex rez(this->re, this->im); rez.re *= c.re;

rez.re -= rez.im * c.im; rez.im *= c.re; rez.im + = rez.re * c.im; return rez;

}

Page 22: POO 6lucrari

Florin Bîrleanu � Programare orientată pe obiecte pentru începători http://igotopia.ro

22

In continuare e ilustrata modalitatea de redefinire a operatorului �+� folosind o functie

prietena: class NrComplex { � public: friend NrComplex operator+ (NrComplex c1, NrComplex c2); }; NrComplex operator+ (NrComplex c1, NrComplex c2); { NrComplex rez; rez.re = c1.re + c2.re; rez.im = c1.im + c2.im; return rez; } 3.2. Exercitii (1) Sa se implementeze clasa AfisorDeNumere si sa se scrie un program de test pentru ea. (2) Sa se scrie cate un program de test pentru fiecare dintre cele doua metode de suprascriere a operatorilor �+� si �*� prezentate (pentru clasa NrComplex). (3) Dupa modelul clasei NrComplex, sa se scrie clasa Vector3D. (Sa se implementeze si metodele ProdusScalar() si ProdusVectorial().)

Bibliografie [1] C++ Operator Overloading Guidelines. http://courses.cms.caltech.edu/cs11/ material/cpp/donnie/cpp-ops.html [2] Operator Overloading in C++. http://courses.cms.caltech.edu/cs11/material/ cpp/donnie/cpp-ops.html

Page 23: POO 6lucrari

Florin Bîrleanu � Programare orientată pe obiecte pentru începători http://igotopia.ro

23

Lucrarea nr. 5

Mostenire

1. Scopul lucrarii

Scopul lucrarii de fata il constituie intelegerea modului in care clasele pot fi reutilizate si extinse prin folosirea mostenirii.

2. Notiuni teoretice Clasele pot fi extinse prin combinarea lor (asa cum am aratat in lucrarea referitoare la compunerea claselor), dar si prin mostenire. Mostenirea in programarea orientata pe obiecte este operatia prin care dintr-o clasa de baza se obtine o clasa derivata. Clasa derivata extinde functionalitatea clasei de baza, specializand-o. Clasa de baza este mai simpla, mai generica, mai abstracta, in vreme ce clasa derivata este mai complexa, mai specifica, mai concreta. Prin mostenire toate elementele clasei de baza se regasesc in clasa derivata, iar la acestea se pot adauga unele noi si se pot modifica comportamente existente. Pentru a intelege ideea de mostenire, ne putem gandi la clasele de forme geometrice cele mai cunoscute. Astfel, daca avem o clasa de baza numita, de exemplu, FormaGeometrica, putem deriva din ea clase ca Triunghi, Patrulater si Elipsa. (Si zicem ca aceste clase mostenesc clasa FormaGeometrica). De asemenea, putem avea si clase ca Trapez si Paralelogram, ce mostenesc clasa Patrulater. In plus, mai putem avea si alte clase, rezultand o ierarhie arborescenta de genul urmator: FormaGeometrica ∟Triunghi ∟Dreptunghic ∟Isoscel ∟Echilateral ∟Patrulater ∟Trapez ∟Paralelogram ∟Dreptunghi ∟Patrat ∟Elipsa ∟Cerc

Chiar daca poate intr-un program nu s-ar justifica decat in rare cazuri

Page 24: POO 6lucrari

Florin Bîrleanu � Programare orientată pe obiecte pentru începători http://igotopia.ro

24

construirea unei asemenea ierarhii de clase derivate unele din altele, ea ilustreaza bine la nivel conceptual in ce consta mostenirea claselor. De exemplu, in arborele de mai sus vedem ca clasa Patrat mosteneste clasa Dreptunghi, care la randul ei mosteneste clasa Paralelogram, care la randul ei mosteneste clasa Patrulater, care la randul ei mosteneste clasa FormaGeometrica. Este evident ca orice patrat este un dreptunghi, iar orice dreptunghi este un paralelogram, iar orice paralelogram este un patrulater, iar orice patrulater este o forma geometrica.

In general, atunci cand zicem ca orice obiect de tip B este si un obiect de tip A inseamna ca B are aceleasi tip de caracteristici ca si A, plus unele detalii. Atfel spus, clasa B mosteneste clasa A (sau, echivalent, clasa B este derivata din clasa A (care este, deci, clasa de baza pentru B)).

Montenirea se realizeaza folosind o constructie C++ de genul urmator: class B : public A { ... };

Tot ce continea clasa A va contine si clasa B, la care se vor adauga noile campuri sau metode pe care le scriem in corpul clasei. In interiorul metodelor adaugate in clasa B (in plus fata de cele importate din clasa A, bineinteles) vom putea avea acces la membrii declarati ca fiind public sau protected din clasa A. Specificatorul de acces protected se utilizeaza doar in contextul mostenirii claselor si are rolul de a face ca respectivele campuri sa nu fie accesibile din exteriorul clasei (ca si cum ar fi fost definite cu private), dar sa fie accesibile din interiorul claselor derivate (caci toti membrii definiti ca fiind private in clasa de baza sunt inaccesibili direct din interiorul noilor metode ale claselor derivate).

Specificatorul de acces utilizat inaintea numelui clasei de baza in exemplul de mai sus hotaraste modul in care specificatorii de acces ai membrilor clasei de baza se vor transforma in clasa derivata. In loc de public puteam folosi acolo fie protected, fie private, efectele fiind redate in continuare:

Specificator mostenire: In clasa de baza: In clasa derivata: public public → public

protected → protected protected public → protected

protected → protected private public → private

protected → protected

O alta problema de interes o constituie modul in care se vor initializa obiectele din clasa derivata. In mod implicit constructorul clasei de derivate apeleaza automat contructorul implicit al clasei de baza. Prin urmare, la construirea unui obiect

Page 25: POO 6lucrari

Florin Bîrleanu � Programare orientată pe obiecte pentru începători http://igotopia.ro

25

apartinand clasei B se vor face mai intai initializarile specifice obiectelor clasei A (caci in fond orice obiect din clasa B este un obiect din clasa A), dupa care se vor putea adauga in constructorul clasei B alte initializari ce sunt necesare.

Daca se doreste, insa, apelarea dintr-un constructor al clasei B nu a constructorului implicit, ci a unui constructor cu parametri, se poate proceda in felul urmator: class A { � public: A(int x); ... }; class B : public A { � public: B(int x); ... }; B::B(int x) : A(x) { // (eventual) alte initializari ... }

Se mai pune problema si cum pot fi diferentiati membrii suprascrisi in clasa derivata. Sa zicem ca in clasa Dreptunghi avem metoda Arie(), iar in clasa derivata Patrat o redefinim. Intrebarea care se pune este cum mai putem avea acces la metoda Arie() care a fost mostenita din clasa Dreptunghi (caci prin suprascrierea metodei cea veche nu se sterge, ci ambele metode raman disponibile). Urmatorul cod arata modul in care se poate solutiona aceasta problema: int Arie()

{ return Dreptunghi::Arie();

}

3. Desfasurarea lucrarii

Exemplele si exercitiile din aceasta lucrare vor fi realizate folosind mediul de dezvoltare Microsoft Visual C++. La crearea proiectului se va alege tipul �Win32

Page 26: POO 6lucrari

Florin Bîrleanu � Programare orientată pe obiecte pentru începători http://igotopia.ro

26

Console Application�. 3.1. Exemplu

Pe langa exemplul discutat in partea teoretica a lucrarii, sa consideram o alta ierahie de clase derivate unele din altele: abstract Animal ← clasa de baza

↓ - caracteristicile generale ale unui animal Caine ← clasa derivata din clasa Animal (si clasa de baza pentru clasa CaineAzor) ↓ - caracteristicile generale ale unui animal ↓ - caracteristici specifice cainilor CaineAzor ← clasa derivata din Caine - caracteristicile de baza ale unui animal - caracteristici specifice cainilor - caracteristici specifice lui Azor concret

Daca ar fi sa reprezentam ca multimi matematice aceste trei clase, am avea ceva de genul urmator: +---------------------------------------------------+ |+-----------------------------------+ Animal | | | +--------------------+ Caine | | | | | CaineAzor | | | | | +--------------------+ | | | +----------------------------------+ | +---------------------------------------------------+

Aceasta diagrama arata foarte clar ca orice caine Azor este un caine, iar orice caine este un animal. Pe de alta parte, insa, trebuie sa avem in vedere faptul ca dimensiunile acestor diagrame nu reflecta realitatea in ceea ce priveste continutul celor trei clase. Ci dimpotriva: clasa Animal contine cele mai putine elemente, la care se adauga alte cateva elemente in clasa Caine, care sunt uterior completate cu alte cateva in clasa CaineAzor. (Termenul �elemente� din ultima afirmatie poate ca nu

este cel mai bine ales, caci poate duce cu gandul la elemente ale multimii. Nu este vorba de asa ceva, ci de elemente descriptive ale respectivei clase de obiecte. Iar aceasta proportionalitate inversa intre numarul de obiecte ale unei clase si numarul de elemente necesare descrierii ei nu este greu de inteles daca ne gandim la cum stau lucrurile in realitate: cu cat dorim sa descriem o clasa mai restransa de obiecte, cu atat avem nevoie de mai multe cuvinte.)

Page 27: POO 6lucrari

Florin Bîrleanu � Programare orientată pe obiecte pentru începători http://igotopia.ro

27

3.2. Exercitii (1) Sa se implementeze ierarhia de clase cu baza in FormaGeometrica. Pentru fiecare clasa sa existe metoda Arie(). Sa se scrie si un program de test. (2) Sa se implementeze si testeze urmatoarea ierarhie de clase: Animal ∟Caine ∟Pisica Fiecare dintre aceste clase va contine metoda Vorbeste() ce va afisa pe ecran un mesaj corespunzator clasei de obiecte respective.

Bibliografie [1] C++ Inheritance. http://www.tutorialspoint.com/cplusplus/cpp_inheritance.htm [2] Introduction to inheritance in C++. http://www.cs.bu.edu/teaching/cpp/ inheritance/intro/ [3] Inheritance. http://www.cppforschool.com/tutorial/inheritance.html

Page 28: POO 6lucrari

Florin Bîrleanu � Programare orientată pe obiecte pentru începători http://igotopia.ro

28

Lucrarea nr. 6

Polimorfism

1. Scopul lucrarii

Lucrarea aceasta isi propune intelegerea a ce este, la ce este util si cum se poate folosi polimorfismul in programarea orientata pe obiecte.

2. Notiuni teoretice

Termenul de polimorfism se refera la ceva ce poate avea mai multe forme. In programarea orientata pe obiecte acest termen este intalnit in doua situatii. Prima dintre ele este polimorfismul parametric, care este doar un alt nume pentru ceea ce se intampla atunci cand suprascriem metode (asa cum am aratat intr-o lucrare anterioara). Cea ce-a doua situatie se refera la polimorfismul propriu-zis, care face obiectul lucrarii de fata.

Polimorfismul se refera la faptul ca un pointer catre o clasa de baza poate primi ca valoare adresa unei clase derivate si ii poate apela versiunea redefinita a unei metode care in clasa de baza a fost declarata folosind cuvantul cheie �virtual�.

Cu alte cuvinte, notiunea de polimorfism e utilizata in contextul mostenirii claselor si al pointerilor catre obiecte.

Sa zicem ca avem o clasa de baza FormaGeometrica si doua clase derivate din aceasta: Dreptunghi si Cerc. Fiecare dintre aceste metode contine metoda Arie() (redefinita in fiecare dintre clasele derivate).

Daca avem un obiect de tip Dreptunghi si un obiect de tip Cerc, putem folosi oricare dintre aceste obiecte in program acolo unde ar fi trebuit sa folosim obiecte de tip FormaGeometrica. Problema este, insa, aceea ca daca dupa ce am facut asta incercam sa le apelam o metoda redefinita, ea nu va fi disponibila (ci se va apelea versiunea metodei mostenita de la clasa de baza).

Daca, insa, in clasa de baza FormaGeometrica definim metoda Arie() ca fiind virtuala (folosind cuvantul �virtual� inaintea declararii antetului metodei), atunci daca

atribui unui obiect de tip pointer catre FormaGeometrica adresa unui obiect de tip Cerc si apelez metoda Arie() folosind pointerul se va apela versiunea redefinita in clasa Cerc a metodei Arie(). Aceasta ne permite sa facem functii care sa opereze cu clase de obiecte generice conform unui comportament prestabilit, urmand ca detalii si extensii sa poata fi adaugate ulterior fara a face modificari in structura programului.

Pentru a intelege mai bine utilitatea polimorfismului, sa ne gandim la urmatoarea aplicatie. Sa zicem ca avem o aplicatie de manipulare simpla a unei

Page 29: POO 6lucrari

Florin Bîrleanu � Programare orientată pe obiecte pentru începători http://igotopia.ro

29

imagini. Aceasta aplicatie contine o fereastra, un spatiu in care poate fi afisata o imagine, un buton de incarcare a imaginii, un buton pentru marire constrast si un buton pentru micsorare contrast. +--------------------------------------------------------------------------------------------------+ |----------------------------------------------------------------------------------------------------| | | | +----------------------------+ | | | Incarca | | | +----------------------------+ | | +----------------------------+ | | | Mareste contrast | | | +----------------------------+ | | +----------------------------+ | | | Micsoreaza contrast | | | +----------------------------+ | | | +--------------------------------------------------------------------------------------------------+ Prin urmare, aplicatia va permite doar incarcarea unei imagini de pe disc si apoi marirea sau micsorarea contrastului ei.

Exista, insa, mai multe tipuri de imagini, ca: imagini binare, imagini in nuante de gri, imagini color, etc. Ceea ce inseamna ca fiecare pixel din imagine poate sa fie fie o valoare binara, fie o valoare scalara, fie o valoare vectoriala, etc. Asta inseamna ca in functie de tipul de imagine atat incarcarea si afisarea imaginii, cat si manipularea contrastului ei pot presupune operatii foarte diferite.

Putem proiecta ca aplicatia sa functioneze generic, considerand un obiect de tip Imagine care contine toate operatiile pe care le putem face cu o imagine, indiferent de ce tip e ea: clasa Imagine: - Incarca(fisier) - Afiseaza() - MaresteContrast() - MicsoreazaContrast.

Apoi putem introduce pe rand suport pentru diverse tipuri de imagini. Partea interesanta consta in faptul ca nu va fi nevoie sa modificam programul deja scris. Daca am proiectat programul astfel incat sa opereze corect cu obiecte de tip Imagine, el va sti sa opereze bine si cu obiecte de tip ImagineColor, de exemplu. Trebuie doar sa definesc clasa ImagineColor care sa mosteneasca clasa Imagine si sa ii redefineasca cele patru metode publice.astfel incat noile metode sa opereze corect cu imagini color.

Page 30: POO 6lucrari

Florin Bîrleanu � Programare orientată pe obiecte pentru începători http://igotopia.ro

30

Un element cheie aici pentru ca lucrurile sa functioneaza asa cum am discutat este, repet, utilizarea cuvantului cheie �virtual� la declararea celor patru metode in

clasa de baza Imagine. De asemenea, un alt element esential este acela ca programul generic trebuie realizat de asa maniera incat sa efectueze manipularile asupra imaginii prin intermediul unui pointer catre un obiect de tip Imagine (clasa de baza). Urmatoarea schita de cod ilustreaza un exemplu: class Imagine { ... public: virtual void Afiseaza(); }; ... class ImagineColor : public Imagine { public: void Afiseaza(); }; ... Imagine *pimg; ImagineColor imgColor;

pimg = &imgColor; p->Afiseaza(); // ← va apela metoda redefinita in clasa ImagineColor

Asadar, polimorfismul e util in special pentru a construi clase care sa opereze

cu obiecte generice, a caror functionare sa nu fie alterata de schimbarea tipului efectiv al obiectului, atata timp cat el se incadreaza in clasa generica de obiecte recunoscute.

3. Desfasurarea lucrarii

Exemplele si exercitiile din aceasta lucrare vor fi realizate folosind mediul de dezvoltare Microsoft Visual C++. La crearea proiectului se va alege tipul �Win32

Console Application�. 3.1. Exemplu

Vom dezvolta in continuare si vom discuta exemplul cu ierharhia de clase FormaGeometrica, Dreptunghi si Cerc. Codul sursa al celor trei clase impreuna cu programul de test este prezentat in continuare: #include <stdio.h>

Page 31: POO 6lucrari

Florin Bîrleanu � Programare orientată pe obiecte pentru începători http://igotopia.ro

31

#include <conio.h> class FormaGeometrica { public: int Arie(); }; int FormaGeometrica::Arie() { return 0; } class Dreptunghi : public FormaGeometrica { private: int a, b; public: Dreptunghi(); Dreptunghi(int a, int b); int Arie(); }; Dreptunghi::Dreptunghi() { a = 0; b = 0; } Dreptunghi::Dreptunghi(int a, int b) { this->a = a; this->b = b; } int Dreptunghi::Arie() { return a*b; } class Cerc : public FormaGeometrica { private: int r; public: Cerc(); Cerc(int r); int Arie(); }; Cerc::Cerc() {

Page 32: POO 6lucrari

Florin Bîrleanu � Programare orientată pe obiecte pentru începători http://igotopia.ro

32

return 0; } Cerc::Cerc(int r) { this->r = r; } int Cerc::Arie() { return 3.14*r*r; } int main(void) { FormaGeometrica *pf; Dreptunghi d(20, 50); Cerc c(30); int arie; pf = &d; arie = pf->Arie(); printf(�%d\n�, arie); // → 0 !!! getch(); pf = &c; arie = pf->Arie(); printf(�%d\n�, arie); // → 0 !!! getch(); return 0; }

Ruland programul se va observa ca pe ecran ariile calculate apar ca fiind zero. Motivul este acela ca pf->Arie() apeleaza FormaGeometrica::Arie() (caci pf este de tip pointer catre un obiect de tip FormaGeometrica, iar atat Dreptunghi, cat si Cerc, sunt tipuri de FormaGeometrica (fiind clase derivate din aceasta), ambele continand, deci, cate o metoda (mostenita) FormaGeometrica::Arie()).

Pentru ca rezultatule programului sa fie cele asteptate trebuie sa activam polimorfismul. Si putem face aceasta definind metoda Arie() ca virtuala in clasa FormaGeometrica: class FormaGeometrica { public: virtual int Arie(); };

Page 33: POO 6lucrari

Florin Bîrleanu � Programare orientată pe obiecte pentru începători http://igotopia.ro

33

Recompiland programul si rulandu-l vom vedea ca de asta data primul pf-

>Arie() returneaza aria dreptunghiului, in vreme ce cel de-al doilea returneaza aria cercului. Acest lucru e posibil datorita legarii dinamice (adica pentru o metoda definita ca virtuala compilatorul nu pune direct apelul catre ea, ci abia la rularea programului se decide ce metoda va fi apelata, in functie de tipul (clasa) obiectului catre care pointerul indica.) 3.2. Exercitii (1) Sa se implementeze programul dat ca exemplu, atat fara �virtual�, cat si cu. (2) Sa se scrie o functie generica ce calculeaza aria unei forme geometrice primite ca parametru, ii citeste tipul si afiseaza aceste informatii pe ecran. Apoi sa se realizeze un program de test care sa verifice aceasta functie trimitandu-i drept parametri obiecte de diverse forme geometrice. Idee: void AfiseazaArie(FormaGeometrica *pf) { printf(�Tip obiect: %s. Arie: %d.\n�, pf->Tip(), pf->Arie()); }

Bibliografie [1] Polymorphism. http://www.cplusplus.com/doc/tutorial/polymorphism/ [2] Introduction to polymorphism in C++. http://www.cs.bu.edu/teaching/cpp/ polymorphism/intro/ [3] Polymorphism in C++. http://www.tutorialspoint.com/cplusplus/ cpp_polymorphism.htm [4] C++ Polymorphism and Abstract Base Class. http://www.codingunit.com/ cplusplus-tutorial-polymorphism-and-abstract-base-class

Page 34: POO 6lucrari

Florin Bîrleanu � Programare orientată pe obiecte pentru începători http://igotopia.ro

34

Aştept întrebările tale pe Facebook la

https://www.facebook.com/florinmarianb

sau pe email la

[email protected]