Documente Academic
Documente Profesional
Documente Cultură
orientat obiect
void Suma(b,c);
begin
c.p_reala:=p_reala+b.p_reala;
c.p_imaginara:=-p_imaginara+b.p_imaginara;
end;
float Modul();
begin
Modul=sqrt(p_reala*p_reala+p_imaginara*p_imaginara);
end;
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).
Definirea atributelor unei clase ca tipuri ale altei clase pune n eviden o
relaie ntre clase i deci ntre obiectele acestora.
Din punct de vedere funcional, metodele unei clase au destinaii diverse.
n multe cazuri i depinznd de limbaj, unei clase i se poate defini o metod (sau
mai multe) constructor i o metod destructor. Un constructor este o metod care
creeaz un obiect, n sensul c i aloc spaiu i/sau iniializeaz atributele acestuia.
Destructorul este o metod care ncheie ciclul de via al unui obiect, elibernd
spaiul pe care acesta l-a ocupat.
ncapsularea exprim proprietatea de opacitate a obiectelor cu privire la
structura lor intern i la modul de implementare a metodelor. Ea este legat de
securitatea programrii, furniznd un mecanism care asigur accesul controlat la
Programarea calculatoarelor
Stiva
Cap: Nod
Partea privat
Contor: Integer
Push ( )
Pop ( )
Partea public (Interfaa)
Top ( )
Empty ( )
Punct
X: int
Y:int X= 100
Deseneaz() Y= 100
Distana(p: punct): float
Cerc
Raza: int
X= 200
Arie():float
Y= 200
Deseneaz()
Raza= 50
Distana(p: punct): float
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.
1
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.
Elemente de programare orientat obiect
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.
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:
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);
}
Exemplu
Adugnd metode accesorii clasei Complex, descrierea acesteia devine:
void Complex::Afiseaza()
{ printf("\n%5.2f%ci*%5.2f\n",p_reala,p_imaginara>=0?'+':'-',
p_imaginara>=0?p_imaginara:-p_imaginara);
}
Elemente de programare orientat obiect
float Complex::GetR()
{ return p_reala;
}
float Complex::GetI()
{ return p_imaginara;
}
void Complex::SetR(float r)
{ p_reala=r;
}
void Complex::SetI(float i)
{ p_imaginara=i;
}
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();
}
produce pe ecran urmtorul rezultat:
5.00-i* 4.00
5.00-i* 4.00
-2.00+i* 3.00
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);
Elemente de programare orientat obiect
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); //a reprezint numarul 3+i*4
Complex b(-1,3.2); //b reprezint numarul -1+i*3.2
Complex c; //incorect
Exemplu
Se definete clasa Complex astfel:
class Complex { float p_reala,p_imaginara;
public:
Complex(float a=0,float b=0);
};
Complex::Complex(float a,float b)
{ p_reala=a;
p_imaginara=b;
}
Putem declara urmtoarele obiecte:
Complex a; //a reprezint numarul 0+i*0
Complex b(-1); //b reprezint numarul -1+i*0
Complex c(2,3); //c reprezint numarul 2+i*3
Complex::Complex()
{
}
Exemplu
Clasa Complex conine un constructor de copiere:
2
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 &
Elemente de programare orientat obiect
Complex::Complex(float a,float b)
{ p_reala=a;
p_imaginara=b;
}
Complex::Complex(Complex &x)
{ p_reala=x.p_reala;
p_imaginara=x.p_imaginara;
}
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
class Complex { float p_reala, p_imaginara;
public
~Complex();
}
Complex::~Complex()
{ //descrierea corpului destructorului
}
Pentru clasa Complex destructorul nu are nimic de fcut i nu e necesar descrierea
unui destructor explicit. Acest exemplu urmrete doar s arate cum se declar un
destructor explicit.
Spre deosebire de constructori, destructorii pot fi apelai explicit, atunci
cnd este necesar tergerea unui obiect. Apelul se face la fel ca pentru orice alt
metod, n contextul obiectului care trebuie ters:
a.~Complex();
Utilizarea destructorilor este obligatorie atunci cnd se lucreaz cu date
dinamice, deoarece destructorii implicii nu pot elibera spaiul alocat dinamic.
n cazul n care la crearea unui obiect au fost apelai mai muli constructori,
la tergerea lui se apeleaz destructorii corespunztori, n ordine invers.
Exemplu
n acest exemplu funcia Afieaz va fi scoas n afara clasei Complex i va fi
declarat ca funcie prieten.
class Complex { float p_reala,p_imaginara;
public:
friend void Afiseaza(Complex x);
Complex(float a=0,float b=0);
Complex(Complex &x);
};
Elemente de programare orientat obiect
void Afiseaza(Complex x)
{ printf("\n%5.2f%ci*%5.2f\n",x.p_reala,x.p_imaginara>=0?'+':'-',
x.p_imaginara>=0?x.p_imaginara:-x.p_imaginara);
}
void main()
{ Complex a(1,2);
Afiseaza(a);
}
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();
if(s.Empty()) printf("\nStiva este goala");
else printf("\nStiva contine date");
}
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.
Exemplu
Fie clasa Punct care implementeaz entitatea punct geometric. Aceasta are
atributele x i y, care reprezint coordonatele punctului n plan. Este inclus o
singur metod, care deseneaz punctul pe ecran (aceast metod nu va
implementat n acest exemplu).
class punct { int x,y;
public:
void deseneaza();
};
void punct::deseneaza()
{ //corpul nu este descris in acest exemplu
}
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
punct a, *pp;
cerc b, *pc;
pp=&a;
pc=&b;
a=b;
pp=pc;
pp=&b;
Nu sunt corecte urmtoarele atribuiri:
pc=&a;
b=a;
pc=pp;
pc=(cerc *)pp;
pc=(cerc *)&a;
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
refer atributul a al clasei derivate, de tip double. Pentru a accesa atributul a
motenit de la clasa printe, n cadrul unei metode a obiectului x trebuie folosit
expresia
Clasa_parinte::a
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
}
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();