Documente Academic
Documente Profesional
Documente Cultură
Elemente de Programare Orientata Obiect
Elemente de Programare Orientata Obiect
orientat obiect
Programarea calculatoarelor
Deoarece o clas este un tip de dat, n definirea unei clase B se pot declara
atribute de tip A, unde A este la rndul ei o clas. Mai mult, o clas A poate defini
atribute de tip A. De exemplu clasa Carte, din figura 10.2 are atributul Autor de
tipul Persoana care este, de asemenea, o clas. Mai mult, Persoana are atributul
Sef care este de acelai tip (Persoana).
Programarea calculatoarelor
Cap: Nod
Contor: Integer
Partea privat
Push ( )
Pop ( )
Top ( )
Empty ( )
X= 100
Y= 100
Cerc
Raza: int
Arie():float
Deseneaz()
Distana(p: punct): float
X= 200
Y= 200
Raza= 50
Programarea calculatoarelor
Programarea calculatoarelor
Membrii unei clase pot fi atribute sau metode. Atributele sunt descrise
asemntor declaraiilor de variabile independente (i asemntor cmpurilor unui
articol struct), specificnd tipul i numele atributului respectiv. Membrii unei
clase pot fi de orice tip, mai puin de acelai tip cu clasa descris (dar pot fi pointeri
ctre clasa descris).
Metodele sunt descrise asemntor funciilor independente. Ele pot fi
descrise integral n interiorul clasei (descriind antetul i corpul lor) sau specificnd
n interiorul clasei doar prototipul funciei, corpul urmnd s fie descris ulterior, n
afara clasei. Este preferat a doua variant, deoarece descrierea clasei este mai
compact dect n primul caz. Atunci cnd se descrie ulterior corpul unei metode,
pentru a specifica apartenena sa la clasa respectiv, numele metodei este prefixat
cu numele clasei din care face parte, folosind operatorul de rezoluie (::), astfel:
tip_rezultat nume_clas::nume_metod(lista parametrilor)
corp metod
Mai mult, funciile care sunt integral descrise n interiorul clasei sunt
considerate funcii inline1, de aceea ele trebuie s fie simple. Pentru funciile mai
complexe, ntotdeauna se recomand s fie descrise folosind a doua variant.
ntruct o clas este un tip de dat, declararea unui obiect se face
asemntor oricrei declaraii de dat:
nume_clas nume_obiect;
Apelul funciilor inline nu produce un salt n segmentul de cod ctre codul executabil al funciei, aa
cum se ntmpl n cazul funciilor obinuite. Pentru aceste funcii, compilatorul insereaz n
program, n locul apelului, secvena de cod corespunztoare corpului funciei, nlocuind parametrii
formali cu valorile actuale. Funciile inline au un comportament asemntor macrodefiniiilor.
Exemplu
Definirea clasei Complex, care implementeaz entitatea matematic numr
complex. Clasa are atributele p_reala i p_imaginara i o metod pentru afiarea
valorii obiectului afiseaza.
class Complex { float p_reala,p_imaginara;
void Afiseaza();
};
void Complex::Afiseaza()
{ printf("\n%5.2f%ci*%5.2f\n",p_reala,p_imaginara>=0?'+':'-',
p_imaginara>=0?p_imaginara:-p_imaginara);
}
Complex tc;
Metoda afieaz ine cont de semnul prii imaginare. Dac aceasta este negativ,
semnul minus este afiat naintea simbolului i al prii imaginare. Se declar
obiectul tc de tipul Complex.
Accesul la membrii obiectului se face folosind operatorul de calificare:
nume_obiect.nume_membru
unde numele obiectului specific din ce obiect este accesat atributul respectiv sau
n contextul crui obiect se execut metoda respectiv. Acest mod de accesare este
folosit atunci cnd se lucreaz cu obiecte statice. n cazul n care nu avem un obiect
ci un pointer ctre un obiect, este necesar i dereferenierea pointerului, nainte de
accesul la membri. Acest lucru este realizat folosind operatorul -> n locul
operatorului de calificare:
p_obiect -> nume_membru
Programarea calculatoarelor
De obicei atributele unei clase sunt declarate ca fiind private, iar metodele
sunt mprite, unele fiind publice (interfaa clasei) i unele private (detalii i
mecanisme interne de implementare a clasei. Dei este tehnic posibil ca toi
membrii unei clase s fie privai, un obiect de acest tip nu poate fi folosit, neavnd
o interfa cu mediul exterior lui. De asemenea, toi membrii unei clase pot fi
publici, dar nu este recomandat aceast tehnic din motive de protecie i
securitate.
Exemplu
n acest context, clasa Complex definit n exemplul anterior nu poate fi folosit,
toi membrii ei fiind privai. Pentru a putea folosi obiecte de tipul Complex, metoda
afieaz trebuie s fie public. Descrierea clasei devine:
class Complex { float p_reala,p_imaginara;
public:
void Afiseaza();
};
void Complex::Afiseaza()
{ printf("\n%5.2f%ci*%5.2f\n",p_reala,p_imaginara>=0?'+':'-',
p_imaginara>=0?p_imaginara:-p_imaginara);
}
Metodele accesorii definite mai sus (GetR, GetI, SetR, SetI) au rolul de a prezenta
valorile atributelor i respectiv de a stabili noi valori pentru ele. n acest exemplu
nu se face nici un fel de control asupra modului n care sunt stabilite noile valori.
Folosind descrierile de mai sus, urmtoarea secven de program:
void main()
{ Complex tc;
Complex *pc;
tc.SetR(5);
tc.SetI(-4);
tc.Afiseaza();
pc=&tc;
pc->Afiseaza();
pc->SetR(-2);
pc->SetI(3);
pc->Afiseaza();
}
Programarea calculatoarelor
10.3 Constructori
Declararea obiectelor are ca efect alocarea de spaiu n memorie, la fel ca
n cazul declarrii oricrei variabile. Acest spaiu nu este iniializat ns. Mai mult,
n cazul n care obiectele clasei au i spaiu extins de memorie, acesta nu este alocat
automat, obiectul declarat fiind astfel incomplet. Atributele unui obiect nu pot fi
iniializate la declarare ntr-o manier asemntoare datelor de tip articol (struct),
deoarece de obicei atributele sunt private, deci inaccesibile din exteriorul
obiectului. Pentru rezolvarea problemei iniializrii obiectelor exist posibilitatea
utilizrii unor metode speciale, numite constructori. La terminarea ciclului de via
al obiectelor, este necesar dezalocarea lor. n general, aceasta se realizeaz
automat, dar n cazul lucrului cu spaiu extins, ea trebuie gestionat n mod explicit.
Problema ncheierii ciclului de via al obiectelor este rezolvat prin utilizarea unor
metode speciale numite destructori. Constructorii i destructorii nu ntorc niciun
rezultat prin numele lor i antetele lor nu precizeaz nici un tip pentru rezultat (nici
mcar void).
Constructorii sunt metode care au acelai nume cu clasa creia i aparin. O
clas poate avea mai muli constructori, cu liste diferite de parametri (ca tip i/sau
numr) metode suprancrcate. Dac nu este definit niciun constructor pentru o
clas, compilatorul va genera un constructor implicit, care nu face dect alocarea
spaiului propriu al obiectului, n momentul n care acesta a fost declarat. Ca
urmare, n acest caz vom avea obiecte neiniializate, urmnd ca iniializarea
atributelor s se fac ulterior, prin intermediul metodelor accesorii. n exemplul
anterior, pentru clasa Complex s-a generat un constructor implicit care aloc spaiu
pentru atributele p_reala i p_imaginara. Iniializarea s-a fcut prin intermediul
metodelor SetR i SetI. n cazul n care clasa prezint cel puin un constructor
explicit, compilatorul nu mai genereaz constructorul implicit. Ca urmare nu se vor
putea declara obiecte neiniializate dac parametrii constructorului nu au valori
implicite.
Constructorii nu pot fi apelai explicit, precum metodele obinuite. Apelul
lor se realizeaz numai la declararea obiectelor. De asemenea, nu se poate
determina adresa constructorilor, aa cum se poate face n cazul funciilor
obinuite. Am vzut mai sus c declaraia unui obiect care nu are constructor
explicit este identic cu declaraia unei variabile simple. n cazul n care clasa
prezint constructori explicii valorile pentru iniializare sunt transmise acestuia la
declararea obiectului, asemntor listei de parametri reali la apelul unei funcii:
nume_clas nume_obiect(lista_valori);
Exemplu
Pentru clasa Complex se poate defini un constructor care s iniializeze cei doi
membri astfel:
class Complex { float p_reala,p_imaginara;
public:
Complex(float a,float b);
};
Complex::Complex(float a,float b)
{ p_reala=a;
p_imaginara=b;
}
Avnd acest constructor n cadrul clasei, nu putem declara obiecte neiniializate (ca
n exemplele anterioare), ci doar obiecte iniializate:
Complex a(3,4);
Complex b(-1,3.2);
Complex c;
Programarea calculatoarelor
//numarul 1+i*0
n C++ este implementat transferul parametrilor prin adres. Pentru a transmite un parametru prin
adres, n lista de parametri se pune naintea numelui su operatorul de refereniere &
//numarul 3+i*4
//numarul 3+i*4
//numarul 3+i*4
10.4 Destructori
Destructorii sunt metode speciale, asemntoare constructorilor, care au rol
invers: ncheierea ciclului de via al obiectelor. Aa cum pentru fiecare clas se
genereaz un constructor implicit (dac nu a fost prevzut unul explicit),
compilatorul genereaz i un destructor implicit, dac nu a fost prevzut unul
explicit. Spre deosebire de constructori, o clas poate avea numai un destructor
explicit. Ca i constructorii, destructorii nu ntorc niciun rezultat. Numele
destructorului este numele clasei precedat de caracterul ~ (tilda). Destructorii nu au
parametri.
Programarea calculatoarelor
Exemplu
Exemplu
S se implementeze clasa Stiv dinamic. O list dinamic este format din noduri,
deci putem defini nti clasa Nod, urmnd a folosi tipul Nod pentru a descrie clasa
Stiv. Pentru acest exemplu, datele memorate n nodurile stivei sunt de tip float.
#include <stdio.h>
typedef float TIP_INFO;
class Nod { TIP_INFO info;
Nod* next;
public:
float GetInfo();
Nod* GetNext();
Nod(float a, Nod* n);
};
float Nod::GetInfo()
{ return info;
}
Nod* Nod::GetNext()
{ return next;
}
Nod::Nod(float a, Nod* n)
{ info=a;
next=n;
}
class Stiva { Nod* Cap;
public:
Stiva();
Stiva(float a);
~Stiva();
void Push(float a);
float Pop();
int Empty();
void Afiseaza();
};
void Stiva::Afiseaza()
{ Nod* x;
x=Cap;
while(x)
{ printf("%5.2f ",x->GetInfo());
x=x->GetNext();
}
}
Stiva::~Stiva()
{ Nod* x;
while(Cap)
{ x=Cap;
Cap=Cap->GetNext();
delete x;
}
}
Programarea calculatoarelor
float Stiva::Pop()
{ float x;
Nod* y;
y=Cap;
x=Cap->GetInfo();
Cap=Cap->GetNext();
delete y;
return x;}
void Stiva::Push(float a)
{ Cap=new Nod(a,Cap);
}
int Stiva::Empty()
{ return Cap?0:1;
}
Stiva::Stiva(float a)
{ Cap= new Nod(a,NULL);
}
Stiva::Stiva()
{ Cap=NULL;
}
void main()
{ Stiva s;
int i;
float x;
if(s.Empty()) printf("\nStiva este goala");
else printf("\nStiva contine date");
for(i=0;i<10;i++)
s.Push((float)i);
s.Afiseaza();
x=s.Pop();
s.Afiseaza();
Clasa Nod conine atributele info (informaia util din nod) i next, iar ca metode
un constructor care iniializeaz atributele obiectului i metode accesorii pentru
accesarea valorilor atributelor.
Clasa Stiva conine un singur atribut, Cap care are ca valoare adresa primului nod
al stivei (vrful stivei). Constructorii clasei asigur crearea unei stive vide sau a
unei stive cu un element. Metodele asigur adugarea unei informaii n stiv,
respectiv extragerea unei informaii. Metoda Afiseaza asigur afiarea pe ecran a
informaiilor din stiv.
Modificator de acces
n lista claselor printe
public
private
public
private
public
private
Nivel acces
n clasa fiu
inaccesibil
inaccesibil
protected
private
public
private
Fie clasa Cerc care implementeaz entitatea geometric cerc. Aceasta este descris
prin coordonatele centrului cercului i raza sa. Ca urmare clasa Cerc poate fi
derivat din clasa Punct, adugnd un nou atribut (raza) i o nou metod, pentru
desenarea cercului.
Programarea calculatoarelor
class cerc: punct
{ float raza;
public:
void deseneaza();
};
void cerc::deseneaza()
{ //corpul nu este descris in acest exemplu
}
Exemplu
Fie o clas Clasa_parinte care are un atribut a de tip float, atribut protejat, i o
clas Clasa_fiu care redefinete atributul a, de tip double. x este un obiect de tipul
Clasa_fiu.
class Clasa_parinte
{ protected:
float a;
//descrierea restului clasei
};
Class Clasa_fiu: public Clasa_parinte
{ protected:
double a;
//descrierea restului clasei
}
Clasa_fiu x;
Expresia
x.a
Programarea calculatoarelor
i apoi destructorii claselor printe, n ordine invers celei n care acestea apar n
lista claselor printe.
Pentru a preciza parametrii reali utilizai pentru fiecare din constructorii
claselor printe, antetul constructorului clasei derivate are o form special:
class Clasa_fiu: clasa_p1, clasa_p2, clasa_p3
{ //attribute
public:
Clasa_fiu();
//constructorul clasei fiu
}
Clasa_fiu::clasa_fiu():clasa_p1(),clasa_p2(),clasa_p3()
{ //descrierea corpului constructorului
}
Programarea calculatoarelor
Pointerul po poate lua ca valoare att adresa unui obiect de tipul cp, ct i adresa
unui obiect de tipul cf.
Fie apelul
po->executa();