Documente Academic
Documente Profesional
Documente Cultură
Clase si obiecte
Clasa = tip de date definit de utilizator, care incapsuleaza atat partea de
structura (date) cat si partea procedurala (metode = functii +
operatori de prelucrare)
= are la baza abstractizarea unei “entitati” (concept),
reprezerntand formalizarea computationala a acesteia
Obiect = variabila (instantiere) care are ca tip de date o clasa
Sintaxa declaratiei: class numeClasa;
Sintaxa definitiei: class numeClasa
(caz clasa nederivata) { declaratii/defintii date/metode (private)
specificator de acces:
declaratie/defintie date/metode
specificator de acces:
declaratie/defintie date/metode
- - - - - - - - - - - - - - - - - - - - - - - - - - - -
}[lista_obiecte];
Clase si obiecte
Specificatori de acces
nr_complex inmultire(nr_complex);
};
Clase si obiecte
Specificatori de acces
nr_complex inmultire(nr_complex);
};
Declaratie functie
Clase si obiecte. Date si functii membre.
. cu sintaxa: Nume_Obiect.membru
-> cu sintaxa: Nume_PointerObiect -> membru
Exemplu:
int main()
{ cl ob1; //definitie obiect
ob1.init(); // acces/apel functie membra
ob1.afisare();
ob1.set(2,3.5);
ob1.afisare();
cl *p_ob; //definitie pointer obiect
p_ob=&ob1;
p_ob->set(20,13.5);// acces/apel functie membra
p_ob->afisare();
}
Clase si obiecte. Date si functii membre.
Exemplu:
class K; // declaratie clasa
Restrictii:
Pentru date:
tip_date clasa::*nume_p_var;
Pentru functii:
Incapsularea datelor
Tehnica incapsularii reprezinta impachetarea la un loc, intr-un singur
tip (abstract) de date, a structurii de date cat si a procedurilor de
prelucrare a acestora.
Accesarea datelor membre se poate face direct, daca specificatorul lor
de acces este public
class cl
{ . . . . . . . . .
public:
int a;
. . . . . . . . .
};
void main()
{ cl ob1;
ob1.a = 3;
}
Clase si obiecte. Incapsularea datelor
Exemplu: class cl
{ int a;
float b;
public:
void SetData(int a1, float b1)
{ a = a1;
b = b1;
}
int Get_a();
{ return a;
}
};
Exemplu:
class cl
{ int a;
static int b;
. . . . . . . . .
};
. . . . . . . . . . . .
int cl::b;
int cl::b = 5;
Clase si obiecte. Date membre de tip static
cl :: b = 5;
ob1 . b = 5;
Clase si obiecte. Date membre de tip static
Exemplu:
int cl::nr_ob;
Clase si obiecte. Date membre de tip static
Pot fi apelate
ob.Get_nr_ob();
cl::Get_nr_ob();
Clase si obiecte. Structurile in C++
Structurile in C++
Structurile sunt similare claselor, pot contine date si proceduri
membre, permit si mosteniri (operatii de derivare) etc.
Singura deosebire este ca tipul de acces la membri unei structuri sunt
in mod implicit de tip public
Spre deosebire de limbajul C, in acest caz numele nou creat este fara
cuvantul cheie struct
Constructori
- Functii (speciale) care sunt apelate automat in momentul
definirii/contruirii unui obiect
- Sunt folositi in general pentru initializarea obiectelor (date membre)
- Pentru aceeasi clasa se pot definii mai multi contructori, ca functii
supraincarcate (alegerea la apel se face dupa regula celei mai bune
potriviri a listei de argumente)
class nume_clasa
{ . . . . . .
public:
nume_clasa(lista argumente){. . . . }
. . . . . .
};
Clase si obiecte. Constructori si destructori
Constructori
Prin definitie, contructorul implicit este constructorul cu lista de
argumente vida
class nume_clasa
{ . . . . . .
public:
nume_clasa()
. . . . . .
};
nume_clasa()
{
}
Clase si obiecte. Constructori si destructori
Constructori
Constructorii trebuie sa aiba specificatori de acces de tip public,
pentru a putea fi apelati de oricunde este nevoie sa definim obiecte din
clasa respectiva
Clase si obiecte. Constructori si destructori
La crearea unui obiect dintr-o clasa, pentru care s-au definit mai multi
constructori, se va apela acel contructor pentru care se potrivesc cel mai
bine argumentele reale (de apel) cu cele formale al contructorului
(conform regulilor de la functii supraincarcate)
class cl int main()
{ int a,b; { cl ob1;
public: cl ob2(3);
cl() cl ob3(4,5);
{ a = b = 0; }
}
cl(int c)
{ a = b = c;
}
cl(int a1, int b1)
{ a = a1;
b = b1;
}
};
Clase si obiecte. Constructori si destructori
La crearea unui obiect dintr-o clasa, pentru care s-au definit mai multi
constructori, se va apela acel contructor pentru care se potrivesc cel mai
bine argumentele reale (de apel) cu cele formale al contructorului
(conform regulilor de la functii supraincarcate)
class cl int main()
{ int a,b; { cl ob1;
public: cl ob2(3);
cl() cl ob3(4,5);
{ a = b = 0; }
}
cl(int c)
{ a = b = c;
}
cl(int a1, int b1)
{ a = a1;
b = b1;
}
};
Clase si obiecte. Constructori si destructori
Destructori
- Functii (speciale) care sunt apelate automat in momentul distrugerii
unui obiect, inclusiv cand acesta este alocat dinamic (utilizand delete)
- Sunt folositi in general pentru operatiile necesare administrarii datelor
membre inainte de distrugerea obiectelor
- NU se supraincarca
Sintaxa: - numele unui destructor este identic cu cel al clasei la care
se adauga prefixul ~ (tilda)
- NU are tip returnat
- NU are lista de argumente
class nume_clasa
{ . . . . . .
public:
~nume_clasa(){. . . . . . }
. . . . . .
};
Clase si obiecte. Constructori si destructori
Destructori
- Daca nu este definit explicit de utilizator, compilatorul genereaza
automat un destructor vid:
~nume_clasa()
{
}
Clase si obiecte. Constructori si destructori
{ cl ob;
. . . . . .
}
Clase si obiecte. Constructori si destructori
Succesiunea etapelor
Succesiunea etapelor
Succesiunea etapelor
Destructori
Similar constructorilor, daca clasa contine date de tip pointer, este bine
sa adminstram operatiile de dealocare a memoriei prin destructori:
class vector
{ int l;
double *v;
public:
vector(){ l = 0; v = NULL; }
vector(int lung_vect)
{ l = lung_vect;
v = new double[l];
if(!v) exit(0);
}
~vector()
{ if (v)
{ delete[] v;
v = NULL;
}
}
};
Clase si obiecte. Constructori si destructori. Constructori de copiere
Constructori de copiere
- Caz particular de constructor, in care argumentul este o referinta la un
obiect din aceeasi clasa
- Scopul utilizari unui astfel de constructor este crearea unui obiect
identic cu cel trimis prin argument
Constructori de copiere
class cl int main()
{ int a; { cl ob1;
float b; cl ob2(2, 3.5);
public:
cl(){ a = 0; b = 0; } cl ob3(ob1);
cl(int a1, float b1) cl ob4 = ob2;
{ a = a1;
b = b1; cl *pob;
} pob = new cl(ob3);
cl(cl &r) }
{ a = r.a;
b = r.b;
}
};
Clase si obiecte. Constructori si destructori. Constructori de copiere
Constructori de copiere
class cl int main()
{ int a; { cl ob1;
float b; cl ob2(2, 3.5);
public:
cl(){ a = 0; b = 0; } cl ob3(ob1);
cl(int a1, float b1)
{ a = a1;
cl ob4 = ob2; ?
b = b1; cl *pob;
} pob = new cl(ob3);
cl(cl &r) }
{ a = r.a;
b = r.b;
}
};
Clase si obiecte. Constructori si destructori. Constructori de copiere
Constructori de copiere
class cl int main()
{ int a; { cl ob1;
float b; cl ob2(2, 3.5);
public:
cl(){ a = 0; b = 0; } cl ob3(ob1);
cl(int a1, float b1)
{ a = a1;
cl ob4 = ob2; ?
b = b1; cl *pob;
} pob = new cl(ob3);
cl(cl &r) }
{ a = r.a;
b = r.b; La initializarea unui obiect la
} definire, se apeleaza
}; constructorul de copiere.
NU este o operatie de atribuire
Clase si obiecte. Constructori si destructori. Constructori de copiere
Constructori de copiere
Constructori de copiere
Constructori de copiere
class vector
{ int l;
double *v;
public:
vector() ~vector()
{ l = 0; { if (v)
v = NULL; { delete[] v;
} v = NULL;
vector(int lung_vect) }
{ l = lung_vect; }
v = new double[l];
if(!v) exit(0); };
}
Clase si obiecte. Constructori si destructori. Constructori de copiere
}
} ? adr1
Ce se intampla la
iesirea din bloc?
Clase si obiecte. Constructori si destructori. Constructori de copiere
Constructori de copiere. Cazul datelor membre cu alocare dinamica
Modificam exemplul:
int main() v1 adr1
{ vector v1(5); 5
. . . . . . . . adr1
{ vector v2 = v1; v2
. . . . . . . . 5
}
} ? adr1
Ce se intampla la
iesirea din bloc?
1. Se apeleaza destructorul lui v2 => eliberarea spatiului de
memorie alocat datei membre v
2. Se distruge variabila statica v2 => eliberarea spatiului de
memorie alocat obiectului v2
Clase si obiecte. Constructori si destructori. Constructori de copiere
Constructori de copiere. Cazul datelor membre cu alocare dinamica
Modificam exemplul:
int main() v1 adr1
{ vector v1(5); 5
. . . . . . . . adr1
{ vector v2 = v1;
. . . . . . . .
}
} ?
Ce se intampla la
iesirea din bloc?
1. Se apeleaza destructorul lui v2 => eliberarea spatiului de
memorie alocat datei membre v
2. Se distruge variabila statica v2 => eliberarea spatiului de
memorie alocat obiectului v2
Ce se obtine in final???
Clase si obiecte. Constructori si destructori. Constructori de copiere
Constructori de copiere. Cazul datelor membre cu alocare dinamica
Modificam exemplul:
int main() v1 adr1
{ vector v1(5); 5
. . . . . . . . adr1
{ vector v2 = v1;
. . . . . . . .
}
} ?
Ce se intampla la
iesirea din bloc?
1. Se apeleaza destructorul lui v2 => eliberarea spatiului de
memorie alocat datei membre v
2. Se distruge variabila statica v2 => eliberarea spatiului de
memorie alocat obiectului v2
int main()
{ vector v1(5);
. . . . . . . .
fct(v1);
. . . . . . . .
}
Clase si obiecte. Constructori si destructori. Constructori de copiere
Constructori de copiere. Cazul datelor membre cu alocare dinamica
Studiu de caz 1: Apel la functie cu parametru obiect dintr-o clasa
void fct(vector v)
{
. . . . . . . . .
}
int main()
{ vector v1(5);
adr1
. . . . . . . . v1
fct(v1); 5
. . . . . . . . adr1
}
Clase si obiecte. Constructori si destructori. Constructori de copiere
Constructori de copiere. Cazul datelor membre cu alocare dinamica
Studiu de caz 1: Apel la functie cu parametru obiect dintr-o clasa
void fct(vector v)
{
. . . . . . . . .
} Apel de functie copiere
variabile de apel in param.
formali ai functie
int main()
vector v = v1
{ vector v1(5);
adr1
. . . . . . . . v1
fct(v1); 5
. . . . . . . . adr1
}
vector fct()
{ vector v(5);
. . . . . . . . .
return v;
}
int main()
{ vector v1 = fct();
. . . . . . . .
}
Clase si obiecte. Constructori si destructori. Constructori de copiere
Constructori de copiere. Cazul datelor membre cu alocare dinamica
Studiu de caz 2: Returnarea din functie a unui obiect
vector fct()
{ vector v(5);
. . . . . . . . .
return v;
}
int main()
{ vector v1 = fct();
. . . . . . . .
// sau similar:
v1 = fct();
}
Clase si obiecte. Constructori si destructori. Constructori de copiere
Constructori de copiere. Cazul datelor membre cu alocare dinamica
Studiu de caz 2: Returnarea din functie a unui obiect
Se defineste si se intializeaza
vector fct() variabila locala v
v
{ vector v(5); 5
adr1
. . . . . . . . . adr1
return v; Apel
} functie
int main()
{ vector v1 = fct();
. . . . . . . .
// sau similar:
v1 = fct();
}
Clase si obiecte. Constructori si destructori. Constructori de copiere
Constructori de copiere. Cazul datelor membre cu alocare dinamica
Studiu de caz 2: Returnarea din functie a unui obiect
Se defineste si se intializeaza
vector fct() variabila locala v
v
{ vector v(5); 5
adr1
. . . . . . . . . adr1
return v;
} temp -> v1
5
int main() adr1
{ vector v1 = fct(); Copie temporara a lui v ce
. . . . . . . . urmeaza sa fie atribuita la
// sau similar: iesirea din functie obiectului v1
v1 = fct();
}
Clase si obiecte. Constructori si destructori. Constructori de copiere
Constructori de copiere. Cazul datelor membre cu alocare dinamica
Studiu de caz 2: Returnarea din functie a unui obiect
Se defineste si se intializeaza
vector fct() variabila locala v
v
{ vector v(5); 5
adr1
. . . . . . . . . adr1
return v;
} temp -> v1
? 5
int main() adr1
{ vector v1 = fct();
Copie temporara a lui v ce
. . . . . . . . urmeaza sa fie atribuita la
// sau similar: iesirea din functie obiectului v1
v1 = fct();
La iesirea din functie se distruge
} obiectul local v:
- apel destructor = eliberare
spatiu alocat dinamic
- distrugere/eliberare spatiu
variabila alocata static
Clase si obiecte. Constructori si destructori. Constructori de copiere
Constructori de copiere. Cazul datelor membre cu alocare dinamica
Studiu de caz 2: Returnarea din functie a unui obiect
vector fct()
{ vector v(5); adr1
. . . . . . . . .
return v;
} v1
5
int main() adr1
{ vector v1 = fct();
. . . . . . . .
// sau similar:
v1 = fct();
}
In final se obtine obiectul v1 care indica o
zona de memorie care nu-i mai este alocata
Clase si obiecte. Constructori si destructori. Constructori de copiere
Constructori de copiere. Cazul datelor membre cu alocare dinamica
Solutia: Definirea unui contructor de copiere propriu care sa
administreze corect alocarea dinamica a spatiului de memorie,
adica sa aloce spatiu dinamic separat in care sa se copieze
continutul primei variabile:
vector::vector(vector &vect)
{ l = vect.l;
v = new int[l];
for(int i=0;i<l;i++)
v[i] = vect.v[i];
}
int main()
{ vector v1(5);
vector v2(v1);
. . . . . . . .
}
Clase si obiecte. Constructori si destructori. Constructori de copiere
Constructori de copiere. Cazul datelor membre cu alocare dinamica
Solutia: Definirea unui contructor de copiere propriu care sa
administreze corect alocarea dinamica a spatiului de memorie,
adica sa aloce spatiu dinamic separat in care sa se copieze
adr1
continutul primei variabile:
v1
vector :: vector(vector &vect) 5
{ l = vect.l; adr1
v = new int[l];
for(int i=0;i<l;i++) v2
v[i] = vect.v[i]; 5 adr2
} adr2
int main()
{ vector v1(5);
vector v2(v1);
. . . . . . . .
}
Clase si obiecte. Constructori si destructori. Constructori de copiere
Constructori de copiere. Cazul datelor membre cu alocare dinamica
Solutia: Definirea unui contructor de copiere propriu care sa
administreze corect alocarea dinamica a spatiului de memorie,
adica sa aloce spatiu dinamic separat in care sa se copieze
adr1
continutul primei variabile:
v1
vector :: vector(vector &vect) 5
{ l = vect.l; adr1
v = new int[l];
for(int i=0;i<l;i++) v2
v[i] = vect.v[i]; 5 adr2
} adr2
ob2 = nr_complex(4.2);
Exemplu:
Etapele distrugerii obiectelor din clase care au date membre de tip clasa
- Mai intai se apeleaza destructorul obiectului curent
- Apoi se apeleaza destructorii obiectelor membre in ordinea inversa
aparitiei in definitia clasei.
construire construire
ob.mx(1) ob.mx()
int main() int main()
ob.my(2) ob.my()
{ Z ob(1,2,3); { Z ob(1);
ob ob
. . . . . . . . . . . .
} distrugere } distrugere
~ob() ~ob()
~ob.my() ~ob.my()
~ob.mx() ~ob.mx()
Clase si obiecte. Obiecte globale. Clase locale
Obiecte globale
Clase locale
Clase imbricate
class Y;
class X
{ int x;
public:
int fct(Y ob)
{ return ob.a;
}
};
class Y
{ int a;
public:
friend int X::fct();
};
Clase si obiecte. Functii si clase friend
Functii si clase friend.
class Y;
class X
{ int x;
public:
int fct(Y ob)
{ return ob.a;
}
};
class Y
{ int a;
public:
friend X;
};
Clase si obiecte. Alocarea dinamica a obiectelor
Alocarea dinamica a obiectelor
delete pob;
delete[] pob;
Clase si obiecte. Supraincarcarea operatorilor
Supraincarcarea operatorilor
Dupa cum se stie, pentru tipurile fundamentale sunt definite o serie de
operatori, care pot fi folositi direct fara alta specificare:
Exemplu: double a = 3.2, b = 5.9, c;
c = a + b;
bool d = a < b;
operator#
simbol operatie: =. +, *
tip_returnat nume_clasa::operator#(lista_de_argumente)
{ bloc instructiuni
}
Clase si obiecte. Supraincarcarea operatorilor prin functii membre ale clasei
int main()
{ NrComplex nr1(2.5,9.4);
NrComplex nr2(4.2,6.1);
NrComplex nr3;
Comentarii:
1. Pentru un operator binar, functia operator primeste un singur argument,
operandul 2 (drept). Operandul 1(stang) este transmis este transmis prin
obiectul prin care se apeleaza functia, adica prin pointer this
2. Apelul de functie operator, este cel corespunzator scrierii operatiilor:
nr3 = nrl + nr2;
care este echivalent cu apelul de functie membra (sintactic corect si se
poate utiliza, insa nu este de dorit):
nr3 = nrl.operator+(nr2);
Comentarii:
4. Este bine ca implementarea functiilor operator sa se faca in sensul
pastrarii semnificatiei operatiei (+ sa nu implementeze scaderea) si sa
respecte, pe cat este posibil, modul de operare definit pentru tipurile
fundamentale:
a) pastrare semnificatie (+ sa implementeze adunare, concatenare)
b) NU modifica niciunul dintre operanzi
c) de cele mai multe ori rezultatul este de acelasi tip cu operanzii
d) SAU poate returna o referinta la obiect de acelasi tip
NrComplex NrComplex::operator~()
{
NrComplex tmp;
tmp.re = re; //echivalent tmp.re = this->re;
tmp.im = - im;
return tmp;
}
Exemplu:
class NrComplex
{ double re, im;
public:
. . . . . . . . . . . . . . . . . . .
friend NrComplex operator+(NrComplex,NrComplex);
friend NrComplex operator*(NrComplex,NrComplex);
friend NrComplex operator~(NrComplex);
};
Clase si obiecte. Supraincarcarea operatorilor prin functii friend
Exemplu (cont.):
Exemplu (cont.):
int main()
{
NrComplex nr1(2.5, 9.4);
NrComplex nr2(4.2, 6.1);
NrComplex nr3;
Particularitati:
- operator binar la care se modifica operandul_stang
- se evalueaza de la dreapt ala stanga
- functia operator=()
- se implementeaza NUMAI prin functie membra nestatica
(adica nu se poate implementa ca functie friend)
- NU se mosteneste
- daca nu este implementata explicit de programator, atunci
compilatorul genereaza automat o functie implicita care transfera
datele membre din operandul drept in cel stang, membru cu membru
Clase si obiecte. Supraincarcarea operatorului de atribuire
- daca clasa are numai date membre alocate static, atunci functia
operator generata automat de compilator este suficienta pentru o
functionare corecta, prin urmare NU mai este nevoie implementarea
explicita (care oricum ar fi similara celei implicite)
Particularitati:
- operator binar
- functia operator[]()
class vector
{ int lung;
double* v;
. . . . . . . . . .
public:
double& operator[](int i)
{
return v[i];
}
};
int main()
{
vector vt(7);
vt[3] = 10; / // utilizare membru
stang op. atribuire
vt[2] = vt[3] + 2.5; // fol. membru drept op.
Clase si obiecte. Supraincarcarea operatorului apel de functie
Particularitati:
- operator binar
- functia operator()()
- se implementeaza NUMAI prin functie membra nestatica
(adica nu se poate implementa ca functie friend)
- operand_stang obiectul curent (transmis prin pointer this)
- operand_drept lista de argumente: insiruire de oricati
parametrii, separati prin virgula. Pot avea orice tip de date si
poate fi folosit in orice scop
Clase si obiecte. Supraincarcarea operatorului apel de functie
Observatii:
Functia operator()()
- se foloseste de obicei pentru implementarea acelei functii care se
utilizeaza cel mai des (din motive de simplificare a scrierii)
- o aplicatie interesanta este cea de indexare a tablourilor
multidimensionale
class cls
{ . . . . . . . . . .
operator TipD ();
};
TipD este tipul de date in care se doreste conversia tipului curent cls
Obs.:
Exista doua metode de converise a tipului de date:
- prin constructor
- prin operator
Particularitati:
- operator unar prefixat = se aplica operandului de dupa operator
- functia operator TipD()
- se implementeaza NUMAI prin functie membra nestatica
(adica nu se poate implementa ca functie friend)
Clase si obiecte. Supraincarcarea operatorului conversie de tip de date (cast)
Observatie:
Daca tipul de date TipD , in care se face conversia, este tot o clasa,
pentru simplificare, este bine ca functia operator TipD() sa aiba
acces la datele membre protejate ale clasei TipD, adica sa fie
declarata functie friend in clasa TipD:
class TipD
{ . . . . . . . . . .
public:
. . . . . . . . . .
friend cls::operator TipD( );
. . . . . . . . . .
};
Clase si obiecte. Supraincarcarea operatorilor de inserare si extragere din stream
Particularitati:
- operatori binari
- functiile operator: operator<<(), operator>>()
NU sunt membre ale clasa definita de utilizator pentru care se face
supraincarcarea, motiv pentru care se RECOMANDA ca ele sa fie
definite ca functii friend ale acestei clase:
class tip_clasa
{ . . . . . . .
public:
. . . . . . .
friend ostream& operator<<(ostream&, tip_clasa);
friend istream& operator>>(istream&, tip_clasa&);
. . . . . . .
};
Clase si obiecte. Supraincarcarea operatorilor de inserare si extragere din stream
Exemplu:
class Pct2D
{ double x,y;
public:
Pct2D()
{ x = y = 0;
}
friend ostream& operator<<(ostream&, Pct2D);
friend istream& operator>>(istream&, Pct2D&);
};
ostream& operator<<(ostream& os, Pct2D p)
{ os << ‘(‘ << p.x << ‘,’ << p.y << ‘)’ << endl;
return os;
}
istream& operator>>(istream& is, Pct2D& p)
{ is >> p.x;
is >> p.y;
return is;
}
Clase si obiecte. Supraincarcarea operatorilor de inserare si extragere din stream
Exemplu (cont.):
int main()
{ Pct2D p1;