Sunteți pe pagina 1din 32

CAPITOLUL 2 Clase i obiecte

2. CLASE I OBIECTE
2.1. Definiia claselor, acces la membri i timp de via
2.2. Instanierea claselor 2.6. Funcii inline
2.3. Membrii unei clase 2.7. Constructori i destructori
2.4. Pointerul this 2.8. Tablouri de obiecte
2.5. Domeniul numelui, vizibilitate 2.9. Funcii prietene (friend)

2.1. DEFINIIA CLASELOR I ACCESUL LA MEMBRII

2.1.1. LEGTURA CLAS-STRUCTUR-UNIUNE

Aa cum s-a subliniat n capitolul anterior, o clas reprezint un tip abstract de date, care
ncapsuleaz att elementele de date (datele membre) pentru care s-a adoptat un anumit mod
de reprezentare, ct i operaiile asupra datelor (funciile membre sau metode). n limbajul
C++, structurile i uniunile reprezint cazuri particulare ale claselor, putnd avea nu numai
date membre sau cmpuri de date, dar i funcii membre. Singura diferen ntre structuri i
uniuni const n faptul c la uniuni, pentru memorarea valorilor datelor membre se folosete -
n comun - aceeai zon de memorie. Deosebirea esenial ntre structuri i uniuni - pe de o
parte - i clase - pe cealat parte - const n modul de acces la membri: la structuri i uniuni
membrii (datele i metodele) sunt implicit publici, iar la clase - implicit privai (membrii sunt
ncapsulai). Lipsa unor modaliti de protecie a datelor face ca tipurile de date introduse prin
structuri sau uniuni s nu poat fi strict controlate n ceea ce privete operaiile executate
asupra lor. n cazul claselor, modul de acces la membrii tipului de date (n scopul protejrii
acestora) poate fi schimbat prin utilizarea modificatorilor de control ai accesului: public,
private, protected.

2.1.2. DECLARAREA CLASELOR

Modul de declarare a unei clase este similar celui de declarare a structurilor i a uniunilor:
class [<nume_tip>]{
<modificator_control_acces>:
<lista_declaraii_membri>;
} [<lista_variabile>];

Clasa reprezint un tip de date (definit de utilizator).


Membrii unei clase sunt:
Datele membre - datele declarate n cadrul clasei;
Metodele - funciile membre, funciile declarate sau definite n cadrul clasei. Se admite c
n cadrul declaraiei de clas s se specifice doar prototipurile funciilor membre,
definiiile putnd fi fcute oriunde n cadrul aceluiai fiier, sau ntr-un alt fiier.
Pentru membrii care apar n lista_membrilor se poate preciza un anumit mod de acces.
Modificator_control_acces poate fi public, private sau protected (eventual
friend, vezi paragraful 2.4.). Dac nu se specific, este considerat cel implicit (private).
PROGRAMAREA ORIENTATA PE OBIECTE, CURS Autor: Diana tefnescu
17
CAPITOLUL 2 Clase i obiecte

Modificatorul de acces public se utilizeaz pentru membrii care dorim s fie neprotejai,
ultimii doi modificatori asigurnd protecia membrilor din domeniul de aciune a lor. Membrii
cu acces private pot fi accesai numai prin metodele clasei (sau prin funciile prietene,
capitolul 2.4.). Cei cu acces protected posed caracteristicile celor privai iar, n plus, pot fi
accesai i din clasele derivate. Specificatorii modului de acces pot apare n declararea clasei
de mai multe ori, n orice ordine.
Domeniul unui modificator de acces ine din punctul n care apare modificatorul respectiv,
pn la sfritul declaraiei clasei sau al ntlnirii altui modificator de acces (exemplele 1,2).

Observaiile legate de prezena <nume_tip> sau <lista_variabile> sunt valabile i n


cazul claselor.
Variabilele din lista_variabile sunt de tipul nume_tip i se numesc instane (obiecte)
ale clasei.

Observaie: n limbajul C++, n cazul tipurilor de date definite cu ajutorul structurilor, se pot
aplica modificatorii de acces. n cazul tipurilor definite cu ajutorul uniunilor, accesul implicit
(public) nu poate fi modificat.

Exemplu:
class masina{
char *culoare; // dat membru la care accesul este, implicit, private
int capacit_cil; // dat membru la care accesul este, implicit, private
public:
void citire_date();
//metod cu acces public, care permite introducerea datelor despre o instan a clasei
int ret_capacit(); //metod cu acces public
};

Membrii culoare i capacitate_cil (accesul private) pot fi accesai doar prin


intermediul metodelor clasei.

Exemplu:
class persoana{
char *nume; //dat membru privat
public:
void citire_inf_pers(); //metod public
private:
int varsta; //dat membru privat
};

Exerciiul 1: S se defineasc tipul de date dreptunghi, cu ajutorul unei structuri, a unei


uniuni i a unei clase.
Datele membre sunt lungimea i limea (variabilele Lung, lat).
Funciile membre sunt:
void seteaza_dimen(double, double) - primete ca argumente dou valori
reale i iniializeaz datele membre cu valorile argumentelor.
double arata_Lung( ) - returneaz valoarea lungimii (a datei membre Lung).
double arata_Lat( ) - returneaz valoarea limii (a datei membre lat).
double calcul_arie( ) - returneaz valoarea ariei dreptunghiului.

PROGRAMAREA ORIENTATA PE OBIECTE, CURS Autor: Diana tefnescu


18
CAPITOLUL 2 Clase i obiecte

//a) Implementarea tipului dreptunghi cu ajutorul unei structuri.


#include <iostream.h>
struct dreptunghi{
double Lung, lat;
void seteaza_dimen(double, double );
//prototipul funciei seteaza_dimen
double arata_Lung()
{return Lung;}
double arata_Lat()
{return lat;}
double calcul_arie()
{return Lung*lat;}
};

void dreptunghi::seteaza_dimen(double L, double l)


{Lung=L; lat=l;}

int main()
{ dreptunghi a;
double l1, l2; cout<<"Lungime="; cin>>l1;
cout<<"Latime="; cin>>l2; a.seteaza_dimen(l1, l2);
// sau: Lung=l1; lat=l2;
cout<<"Dimensiunile dreptunghiului sunt:";
cout<<a.arata_Lung();
cout<<" si"<<a.arata_Lat()<<'\n';
cout<<"Aria dreptunghiului:"<<a.calcul_arie()<<'\n';
cout<<"Dimens structurii:"<<sizeof(a)<<'\n';
}

//b) Implementarea tipului dreptunghi cu ajutorul unei uniuni


#include <iostream.h>
union dreptunghi{
double Lung, lat;
void seteaza_dimen(double, double );
double arata_Lung()
{return Lung;}
double arata_Lat()
{return lat;}
double calcul_arie(double s)
{return s*lat;}
};

void dreptunghi::seteaza_dimen(double L, double l)


{Lung=L; lat=l;}

int main()
{ dreptunghi a; double l1, l2;
cout<<"Lungime="; cin>>l1; cout<<"Latime="; cin>>l2;
a.seteaza_dimen(l1, l1);
cout<<"Lung. drept:"<<a.arata_Lung()<<'\n';
double s1=a.arata_Lung(); a.seteaza_dimen(l2, l2);
cout<<"Latimea dreptunghiului este:";
cout<<a.arata_Lat()<<'\n';
cout<<"Aria dreptunghiului:"<<a.calcul_arie(s1)<<'\n';
cout<<"Dimens. uniunii:"<<sizeof(dreptunghi)<<'\n';
}

PROGRAMAREA ORIENTATA PE OBIECTE, CURS Autor: Diana tefnescu


19
CAPITOLUL 2 Clase i obiecte

n exerciiul 1 a, b se definete tipul dreptunghi printr-o structur, respectiv o uniune. Tipul


conine att datele membre, ct i metodele care implementeaz operaiile care pot fi realizate
asupra variabilelor de tipul dreptunghi. Metodele arata_Lung, arata_Lat, calcul_arie
sunt definite n structur (uniune). Metoda seteaza_dimen este doar declarat n interiorul
structurii (uniunii), fiind abia apoi definit. n varianta b (implementarea cu uniune, unde
pentru memorarea valorilor datelor membre se utilizeaz aceeai zon de memorie), pentru a
pstra valorile att pentru lungimea dreptunghiului, ct i pentru lime, metodele au fost
modificate.

Nespecificnd nici un modificator de control al accesului, toi membrii (date i metode) sunt
implicit publici. De aceea, de exemplu, atribuirea unei valori pentru data membr Lung se
putea realiza, la fel de bine, n corpul funciei main, astfel: Lung=l1; (n exerciiul 1a,
atribuirea se realizeaz cu ajutorul metodei seteaza_dimen).

//c) Implementarea tipului dreptunghi cu ajutorul unei clase


#include <iostream.h>
class dreptunghi{
double Lung, lat;
public:
void seteaza_dimen(double, double );
double arata_Lung() {return Lung;}
double arata_Lat() {return lat;}
double calcul_arie() {return Lung*lat;}
};

void dreptunghi::seteaza_dimen(double L, double l)


{Lung=L; lat=l;}
int main()
{ dreptunghi a;double l1, l2;
cout<<"Lungime="; cin>>l1;cout<<"Latime="; cin>>l2;
a.seteaza_dimen(l1, l2);
cout<<"Dimensiunile dreptunghiului sunt:";
cout<<a.arata_Lung()<<" si"<<a.arata_Lat()<<'\n';
cout<<"Aria dreptunghiului:"<<a.calcul_arie()<<'\n';
cout<<"Dimens :"<<sizeof(a)<<'\n';
}

n exerciiul 1c se definete tipul de date dreptunghi cu ajutorul unei clase. Nivelul de


acees implicit la membrii clasei este private. Dac pentru metode nu s-ar fi folosit
modificatorul de acces public, metodele nu ar fi putut fi folosite n funcia main.

Observaii:
1. Pentru fiecare membru (dat membru sau metod) al unei clase se poate specifica modul
de control al accesului. Membrii publici (vizibili, accesibili din exterior) constituie
interfaa public a clasei, iar membrii privai (ncapsulai, ascuni) ofer descrierea datelor
membre ale fiecrei instane a clasei i detalii de implementare particulare clasei
respective.
2. Reamintim c, pentru a indica faptul c metoda seteaz_dimen aparine tipului
dreptunghi, se folosete operatorul scop :: (de apartenen). Astfel, la definirea
metodei, prototipul ei va fi:
void dreptunghi::seteaza_dimen(double L, double l);
3. A defini o clas presupune declararea acesteia i definirea tuturor metodelor sale.

PROGRAMAREA ORIENTATA PE OBIECTE, CURS Autor: Diana tefnescu


20
CAPITOLUL 2 Clase i obiecte

Exerciiul 1: S se defineasc tipul de date data, cu ajutorul unei structuri i a unei clase.

/* tipul data implementat cu ajutorul unei clase. */


#include <iostream.h>
struct data {
int luna, zi, an;
void afiseaza(void);
};

void data::afiseaza()
{ char *den_lun[] = {
"Ianuarie","Februarie","Martie","Aprilie","Mai","Iunie",
"Iulie","August","Septembrie","Octombrie","Noiembrie",
"Decembrie"};
cout << den_lun[luna-1] << " " << zi << ", " << an; }

main()
{ data dat_nast= {4, 6, 1980};
cout << "\nData de nastere a lui Andrei este ";
dat_nast.afiseaza();
int a,z,l;
cout<<"Ziua in care te-ai nascut:"; cin>>z;
cout<<"Luna in care te-ai nascut:"; cin>>l;
cout<<"Anul in care te-ai nascut:"; cin>>a;
data dat_nast_ta = {l, z, a};
cout << "\nData nasterii tale este: "; dat_nast_ta.afiseaza();
}

/* tipul data implementat cu ajutorul unei clase. */


#include <iostream.h>
class data {
int luna, zi, an;
public:
void initializare(int, int, int);
void afiseaza(void);
};

void data::initializare(int ll, int zz, int aa)


{luna=ll; zi=zz; an=aa;}

void data::afiseaza()
{ char *den_lun[] = {
"Ianuarie","Februarie","Martie","Aprilie","Mai","Iunie",
"Iulie","August","Septembrie","Octombrie","Noiembrie",
"Decembrie"};
cout << den_lun[luna-1] << " " << zi << ", " << an; }

main()
{ data dat_nast;
dat_nast.initializare(4, 6, 1980);
cout << "\nData de nastere a lui Andrei este ";
dat_nast.afiseaza();

int a,z,l;
cout<<"Ziua in care te-ai nascut:"; cin>>z;

PROGRAMAREA ORIENTATA PE OBIECTE, CURS Autor: Diana tefnescu


21
CAPITOLUL 2 Clase i obiecte

cout<<"Luna in care te-ai nascut:"; cin>>l;


cout<<"Anul in care te-ai nascut:"; cin>>a;
data dat_nast_ta;
dat_nast_ta.initializare(l, z, a);
cout << "\nData nasterii tale este: ";
dat_nast_ta.afiseaza(); }

Observaii:
1. n ambele situaii, n funcia main se declar instanele data_nast i dat_nast_ta.
2. n primul caz tipul este introdus cu ajutorul unei structuri la care membrii sunt, implicit,
publici. De aceea, iniializarea se poate face, direct, n funcia main.
3. n al doilea caz, datele membre sunt implicit private i de aceea, iniializarea lor se poate
realiza doar prin intermediul metodei initializare, apelat pentru fiecare instan a
clasei.

2.2. INSTANIEREA CLASELOR


Instanierea unei clase const n declararea unor variabile de tip definit cu ajutorul clasei. O
astfel de variabil, numit obiect (sau instan a clasei) este o dat de tip definit prin clas. n
exerciiul anterior (punctul c), n funcia main, se declar obiectul (variabila) a de tip
dreptunghi. Spunem c obiectul a este o instan a clasei dreptunghi. Se pot declara
oricte obiecte (instane) ale clasei. Aa cum se observ din exemplu, declararea obiectelor de
un anumit tip are o form asemntoare celei pentru datele de tip predefinit:
<nume_clasa> <lista_obiecte>;
Exemple:
dreptunghi a;
dreptunghi b, c, d;

2.3. MEMBRII UNEI CLASE


Datele membru se aloc distinct pentru fiecare instan (atribute ale instanei) a clasei (pentru
declararea obiectelor a, b, c, d de tip dreprunghi, vezi figura 2.1.). Excepia de la aceast
regul o constituie datele membru statice, care exist ntr-un singur exemplar, comun, pentru
toate instanele clasei.

a.Lung Lung b.Lung Lung c.Lung


Lung

lat a.lat lat b.lat lat c.lat


a b c

Lung d.Lung

lat d.lat
d

Figura 2.1. Alocarea memoriei pentru datele membre nestatice

Metodele figureaz ntr-un singur exemplar, oricte instane ale clasei ar exista.
PROGRAMAREA ORIENTATA PE OBIECTE, CURS Autor: Diana tefnescu
22
CAPITOLUL 2 Clase i obiecte

n exemplul anterior, metoda seteaza_dimen este doar declarat n interiorul clasei, fiind
abia apoi definit. La definirea funciei
(void dreptunghi::seteaza_dimen(double L, double l)) s-a folosit operatorul
:: (scope resolution operator) care specific relaia de apartenen a metodei la tipul
dreptunghi.
Operatorul cupleaz <nume_clasa>::<nume_functie_membru> i definete
domeniul (scopul) n care acea funcie va fi recunoscut. Prezena numelui clasei n faa
funciei membru este obligatorie, deoarece, altfel nu s-ar putea face distincia ntre metode cu
nume identice (cu acelai prototip), care aparin unor clase diferite.

O funcie membru se apeleaz totdeauna n strns dependen cu un obiect din clasa


respectiv. Legtura dintre obiect i funcia membr se face prin operatorul . sau operatorul
->, dup cum obiectul este desemnat prin nume sau prin pointer (vezi exemplul 1).

n plus, metodele statice pot fi apelate independent de un obiect al clasei, folosind operatorul
de rezoluie (::).
Accesul la o metod presupune o activitate de adresare, transparent utilizatorului. De fapt, n
interiorul obiectului creat se afl doar punctatori la clasa din care provin. n interiorul
definiiei clasei se aloc o singur copie a fiecrei funcie membr i punctatorii respectiv,
prin care obiectul va avea acces la metoda respectiv. Excepia de la aceast regul o
constituie metodele virtuale (capitolul 4).

Exemplul 1: Fie clasa dreptunghi din exerciiul anterior.

class dreptunghi{
double Lung, lat;
public:
void seteaza_dimen(double, double );
double arata_Lung();
double arata_Lat();
double calcul_arie();
};
//..
main()
{ dreptunghi a;
//
cout<<"Aria dreptunghiului:"<<a.calcul_arie()<<'\n';
dreptunghi *pa;
pa=&a;
double arie=pa->calcul_arie(); }

Exemplul 2: Se implementeaz tipul Data (pentru data calendaristic).

#include <iostream.h>
class Data {
int luna, zi, an;
public:
void initializ(int l, int z, int a) {luna=l; zi=z; an=a; }
int get_an() { return an; } // functie membra care returneaza anul
int get_luna() { return luna; } // functie membra care returneaza luna
int get_zi() { return zi; }
int& an_data() { return an; } /* functie membra care permite
schimbarea valorii datei membre an */
PROGRAMAREA ORIENTATA PE OBIECTE, CURS Autor: Diana tefnescu
23
CAPITOLUL 2 Clase i obiecte

int& luna_data() { return luna; }


int& zi_data() { return zi; }
};

main()
{ Data dt; dt.initializ(4, 1, 89);
cout << "\nAnul este: " << dt.get_an();
cout << "\nZiua este: " << dt.get_zi();
cout << "\nLuna este: " << dt.get_luna();
// ------ folosirea metodelor care schimba anul, luna si ziua pentru instanta dt
dt.an_data() = 90;dt.luna_data()=12; dt.zi_data()=31;
cout << "\nNoul an este: " << dt.get_an();
cout << "\nNoua luna este: " << dt.get_luna();
cout << "\nNoua zi este: " << dt.get_zi(); }

Exerciiu: S urmrim exerciiul urmtor, care ilustreaz problemele legate de membrii


statici ai unei clase (figura 2.2.).

#include <iostream.h>
#include <conio.h>
class exemplu
{ int i; // dat membr privat, acces la ea doar prin metode
public:
static int contor;
// dat membr publica,
//neprotejat (scop didactic)
void inc(void)
{i++;}
void arata_i()
{cout<<"i="<<i<<'\n';} exemplu::contor a1.i
void inc_contor(void)
{contor++;}
a2.i
void init(void)
{i=0;}
static void arata_contor() a3.i
{cout<<"Contor=";
cout<<contor<<'\n';}
static void functie(exemplu*);
} a1, a2, a3;

int exemplu::contor=0; Figura 2.2. Alocarea memoriei pentru


//iniialiazarea datei membru statice datele membru statice i nestatice

void exemplu::functie (exemplu *pe)


{//i+=3;
//eroare, nu se cunoaste obiectul care-l poseda pe i
pe->i++;
//corect, este specificat proprietarul lui i
contor++; //variabil static, comun tuturor obiectelor
}

main()
{
a1.init(); a2.init(); a3.init(); //a1.i=0, a2.i=0, a3.i=0
a1.arata_i();a2.arata_i();a3.arata_i(); //i=0, i=0, i=0

PROGRAMAREA ORIENTATA PE OBIECTE, CURS Autor: Diana tefnescu


24
CAPITOLUL 2 Clase i obiecte

a1.inc(); a2.inc(); a3.inc(); //a1.i=1, a2.i=1, a3.i=1


a1.arata_i();a2.arata_i();a3.arata_i(); //i=1, i=1, i=1
a1.functie(&a1); //contor=1, i=2
exemplu::functie(&a2); //contor=2, i=2
//functie(); //incorect
a1.inc_contor(); //contor=3
exemplu::arata_contor();
a2.inc_contor(); //contor=4
exemplu::arata_contor();
a3.inc_contor(); //contor=5
exemplu::arata_contor();
exemplu::arata_contor();
exemplu::contor+=100; // membru public; contor=105
cout<<"Contor="<<exemplu::contor<<'\n'; // Contor=105
}

Din exemplul anterior, se poate observa c metoda static funcie poate fi apelat ca o
metod obinuit, sau folosind operatorul ::. Pentru data membr static contor se rezerv
o zon de memorie comun obiectelor a1, a2, a3. Pentru data membr i se realizeaz o
copie pentru fiecare instan a clasei. Deasemenea, deoarece data membr contor este
static, nu aparine unui anume obiect, ea apare prefixat de numele clasei i operatorul de
apartenen.

Exerciiu: S se urmreasc urmtorul exerciiu, care definete tipul ex_mstat, cu o dat


membru static (s) i metodele statice (set_s, ret_s).

#include <iostream.h>
class ex_mstat{
int a; static double s; ex_mstat::s
public:
int ret_a()
{return a;}
void set_a(int x) a a
{a=x;} p q
static double ret_s()
{return s;}
static void set_s(double x)
{s=x;} Figura 2.3. Alocarea memoriei pentru
void set1_s(double x) membrii clasei ex_mstat
{s=x;}
double ret1_s()
{return s;}
};

double ex_mstat::s;
/*se rezerv spaiu n memorie pentru data membr static s, care figureaz ntr-un singur
exemplar pentru toate instaele clasei ex_mstat (figura 2.3.)*/
main()
{ex_mstat p,q;
p.set_a(100);
p.set_s(200); q.set_a(300);
cout<<"p.a="<<p.ret_a()<<" p.s="<<p.ret_s();
cout<<" ex_mstat::ret_s="<<ex_mstat::ret_s()<<'\n';
PROGRAMAREA ORIENTATA PE OBIECTE, CURS Autor: Diana tefnescu
25
CAPITOLUL 2 Clase i obiecte

//p.a=100 p.s=200 ex_mstat::ret_s=200


cout<<"q.a="<<q.ret_a()<<" q.s="<<q.ret1_s();
cout<<" ex_mstat::ret_s="<<ex_mstat::ret_s()<<'\n';
//q.a=300 q.s=200 ex_mstat::ret_s=200
ex_mstat::set_s(500.20);
cout<<"p.a="<<p.ret_a()<<" p.s="<<p.ret_s();
cout<<" ex_mstat::ret_s()="<<ex_mstat::ret_s()<<'\n';
//p.a=100 p.s=500.20 ex_mstat::ret_s=500.20
cout<<"q.a="<<q.ret_a()<<" q.s="<<q.ret1_s();
cout<<" ex_mstat::ret_s()="<<ex_mstat::ret_s()<<'\n';
//q.a=300 q.s=500.20 ex_mstat::ret_s=500.20
q.set1_s(800.80);
cout<<"p.a="<<p.ret_a()<<" p.s="<<p.ret_s();
cout<<" ex_mstat::ret_s()="<<ex_mstat::ret_s()<<'\n';
//p.a=100 p.s=800.20 ex_mstat::ret_s=800.20
cout<<"q.a="<<q.ret_a()<<" q.s="<<q.ret1_s();
cout<<" ex_mstat::ret_s()="<<ex_mstat::ret_s()<<'\n';
//q.a=300 q.s=800.20 ex_mstat::ret_s=800.20
p.set1_s(999);
cout<<"p.a="<<p.ret_a()<<" p.s="<<p.ret_s();
cout<<" ex_mstat::ret_s()="<<ex_mstat::ret_s()<<'\n';
//p.a=100 p.s=999 ex_mstat::ret_s=999
cout<<"q.a="<<q.ret_a()<<" q.s="<<q.ret1_s();
cout<<" ex_mstat::ret_s()="<<ex_mstat::ret_s()<<'\n';
//q.a=300 q.s=999 ex_mstat::ret_s=999
}

Aa cum se observ din exemplul anterior, data membru static s figureaz ntr-un singur
exemplar pentru instanele p i q. Ea poate fi modificat prin metoda static set_s sau prin
metoda set1_s.
Apelul unei metode statice poate fi realizat ca un apel al unei metode obinuite:
p.ret_s(), sau folosind operatorul de rezoluie: ex_mstat::ret_s(). Datorit ultimului
mod de apel, n care metoda static nu este asociat unui obiect anume, n corpul funciilor
statice, nu pot fi accesate dect datele membre statice.

Observaie: Nu trebuie confundai membrii statici ai unei clase cu datele care au clasa de
memorare static.

2.4. POINTERUL THIS


Fiecare funcie membr posed un argument ascuns, numit this, argument transmis n mod
automat de ctre compilator. Aceast variabil (local funciilor membru) reprezint pointerul
ctre obiectul curent (cel care apeleaz metoda). S reimplementm metoda calcul_arie,
folosind acest pointer (dei, n aceast situaie, utilizarea pointerului this este redundant).

Exemplu:
class dreptunghi{
double Lung, lat;
public:
//..
void seteaza_dimen(double, double);
};

PROGRAMAREA ORIENTATA PE OBIECTE, CURS Autor: Diana tefnescu


26
CAPITOLUL 2 Clase i obiecte

void dreptunghi::seteaza_dimen(double L, double l)


{//Lung=L; lat=l; this->Lung=L; this->lat=l;}

Deoarece o metod static se apeleaz independent de un obiect al clasei, pointerul this nu


mai poate fi utilizat.

2.5. DOMENIUL UNUI NUME, VIZIBILITATE I TIMP DE VIA


nainte de a citi acest paragraf, trebuie revzute notiunile de timp de viata si domeniu de
vizibilitate.

2.5.1. Domeniul unui nume

Unui nume i corespunde un domeniu, specificat prin declaraia variabilei. n funcie de


poziia declaraiei (definirii) unui nume, n limbajul C++, domeniul poate fi:
local (dac numele este declarat ntr-un bloc);
fiier (dac numele este declarat n afara oricrui bloc sau declaraie (definiie) de
clas);
clas.

Dac un nume care are ca domeniu un fiier este redefinit ntr-un bloc inclus n domeniul su,
el poate fi folosit n acest bloc dac este precedat de operatorul rezoluie.
Exemplu:
#include <iostream.h>
int i=80; // i declarat n afara oricrei funcii, domeniul numelui este fiierul
main()
{double i=99.9; // redeclararea variabilei i , ncepe domeniul local
cout<<"Valoarea lui i="<<i<<'\n'; // Valoarea lui i=80
cout<<"Valoarea lui i="<<::i<<'\n'; } // Valoarea lui i=99.9

Domeniul numelui unui tip de date definit printr-o clas (structur sau uniune, deoarece
acestea sunt cazuri particulare de clase, cu toi membrii publici) se stabilete n mod similar
domeniului oricrei variabile. Numele unui membru al unei clase are un domeniu de tip
clas. Ca orice nume, un nume de clas poate fi redeclarat.
Exemplu:
class a{
//
};
//..
{ //instruciune bloc aflat n domeniul numelui a
double a=99; //redeclararea lui a
class::a x; //x este un obiect de tipul a (definit printr-o clas)
}

2.5.2. Vizibilitate

Domeniul de vizibilitate a unei variabile (obiect) este determinat de clasa de memorare a


variabilei (obiectului). De obicei, domeniul de vizibilitate al unui nume coincide cu domeniul
numelui.

PROGRAMAREA ORIENTATA PE OBIECTE, CURS Autor: Diana tefnescu


27
CAPITOLUL 2 Clase i obiecte

2.5.3. Timp de via

Timpul de via a unei variabile (obiect) este determinat de clasa de memorare a variabilei
(obiectului. n limbajul C++, alocarea dinamic a memoriei se realizeaz cu operatorii new i
delete (vezi i capitolul 3).

2.6. FUNCII INLINE


La apelul unei funcii obinuite se ntrerupe execuia funciei apelante i se execut un salt la
adresa de memorie la care se gsete corpul funciei apelate. La terminarea execuiei funciei
apelate se revine n funcia apelant, relundu-se execuia cu instruciunea imediat urmtoare
apelului de funcie. n situaiile n care corpul funciei apelate este format din cteva
instruciuni, operaiile descrise anterior (implicate n apel i revenire) pot fi mai complicate
dect un apel prin expandare (n care apelul funciei n funcia apelant este nlocuit cu nsui
corpul funciei apelate). Pentru eliminarea acestor dezavantaje, se folosesc funciile inline.

Prezena funciilor inline anun compilatorul s nu mai genereze instruciunile n cod main
necesare apelului i revenirii, ceea ce conduce la mrirea timpului de compilare n favoarea
micorrii timpului de execuie. Utilizarea funciilor inline se justific doar n situaiile n care
codul generat de compilator pentru execuia corpului funciei este mai mic dect codul generat
pentru apel i revenire.

Practic, funciile care au corpul format din maximum trei instruciuni i nu conin instruciuni
repetitive (for, while, do-while), pot fi declarate inline. Declararea unei funcii
inline se realizeaz explicit, specificnd n antetul funciei respective cuvntul cheie inline.
inline <tip_val_ret> <nume_fct> (<lista_declar_par_formali>);

n cazul metodelor unei clase, dac acestea sunt definite n interiorul clasei, ele sunt
considerate, implicit, funcii inline (n exerciiul anterior, funciile arat_Lung, arat_Lat
i calcul_arie sunt, implicit, funcii inline).

Exist i posibilitatea de a declara metoda la declararea clasei i de a specifica, explicit, c


este funcie inline la definirea funciei.

Exemplu: Dac se dorete ca metoda seteaza_dim din exerciiul anterior s fie funcie
inline, fr a modifica declaraia tipului dreptunghi, se poate proceda astfel:
class dreptunghi{
// . . .
public:
// . . .
void seteaza_dimen(double, double );// declararea metodei
// . . .
};
inline void dreptunghi::seteaza_dimen(double L, double l)
//funcie inline, explicit
{Lung=L; lat=l;}

Prefixarea definiiei funciei seteaza_dimen cu cuvntul cheie inline este echivalent cu


definirea metodei n cadrul declaraiei clasei dreptunghi.

PROGRAMAREA ORIENTATA PE OBIECTE, CURS Autor: Diana tefnescu


28
CAPITOLUL 2 Clase i obiecte

Exerciiu: S se defineasc tipul de date complex, cu datele membru parte real i parte
imaginar. Operaiile care pot fi realizate asupra datelor de acest tip, vor fi:
Citirea unei date de tip complex (citirea valorilor pentru partea real i cea imaginar);
afiarea unei date de tip complex; calculul modulului unui complex; calculul argumentului
unui complex; incrementarea prii imaginare; decrementarea prii imaginare; funcii care
returneaz valoarea prii reale i a prii imaginare a unei date de tip complex; adunarea a
dou date de tip complex; nmulirea a dou date de tip complex.

#include <iostream.h>
#include <math.h>
#define PI 3.14159
class complex{
double real, imag;
public:
int citire();
void afisare();
double modul();
double arg();
void incrpi() /*incrementeaza partea imaginara; FUNCIE INLINE, implicit,
fiind definit n interiorul clasei */
{ imag++;}
inline void decrpi(); //decrementarea partii imaginare
double retreal(); //returneaza partea reala
double retimag(); //returneaza partea imaginara
void adun_c(complex, complex); //aduna 2 numere complexe
void inm_c(complex*, complex*); //produsul a 2 numere complexe
};

inline double complex::modul()


{ return sqrt(real*real+imag*imag);}
int complex::citire()
{ cout<<"P. reala:"; if (!(cin>>real)) return 0;
cout<<"P. imag:";if (!(cin>>imag)) return 0 ;
return 1; }
void complex::afisare()
{ if (imag>=0)
cout<<real<<"+"<<imag<<"*i"<<"\n";
else cout<<real<<imag<<"*i\n";}
double complex::arg()
{if (real==0 && imag==0) return 0.0;
if (imag==0) //z=p. reala
if (real>0) return 0.0;
else return PI;
if (real==0)
if (imag>0) return PI/2;
else return (3*PI)/2;
double x=atan(imag/real);
if (real<0) return PI+x;
if (imag<0) return 2*PI+x;
return x;}
inline void complex::decrpi()
{ imag--;}
double complex::retreal()
{ return real;}

PROGRAMAREA ORIENTATA PE OBIECTE, CURS Autor: Diana tefnescu


29
CAPITOLUL 2 Clase i obiecte

double complex::retimag()
{ return imag; }
void complex::adun_c (complex x1, complex x2)
{real=x1.real+x2.real;
imag=x1.imag+x2.imag;}
void complex::inm_c(complex *x1, complex *x2)
{real=x1->real*x2->real-x1->imag*x2->imag;
imag=x1->real*x2->imag+x1->imag*x2->real;}

main()
{complex z1;z1.citire();cout<<"z1=";z1.afisare();
complex z2;z2.citire();cout<<"z2=";z2.afisare();
cout<<"Modulul z2="<<z2.modul()<<'\n';
cout<<"Agument z2="<<z2.arg()<<'\n';
cout<<"P. reala z2="<<z2.retreal();
cout<<"P imag z2="<<z2.retimag()<<'\n';
z2.incrpi();cout<<"Dupa increm p imag=";
cout<<z2.retimag()<<'\n';z2.afisare();
complex z3;z3.adun_c(z1,z2);cout<<"Adunare z1+z2=";z3.afisare();
complex*pz1=&z1,*pz2=&z2;z3.inm_c(pz1,pz2);
cout<<"Inmultire z1+z2=";z3.afisare();}

2.7. CONSTRUCTORI I DESTRUCTORI

2.7.1. INIIALIZAREA DATELOR

La declararea datelor de tip predefinit sau definit de utilizator prin structuri, uniuni sau clase,
compilatorul aloc o zon de memorie corespunztoare tipului respectiv. Este indicat ca n
cazul n care datele structurate au ca membrii pointeri, s se aloce memorie n mod dinamic.

n general, datele statice sunt iniializate automat cu valoarea 0. Celelalte categorii de date, nu
sunt iniializate. Iniializarea datelor simple de tip predefinit se poate realiza dup declararea
acestora, sau n momentul declarrii.

Exemple:
int i; i=30; // declararea variabilei i, apoi iniializarea ei prin atribuire
char c='A'; // declararea i iniializarea variabilei c

Iniializarea datelor structurate se poate realiza n momentul declarrii acestora, prin listele de
iniializare.

Exemple:
//1 declararea i iniializarea vectorului a
int a[]={20, 30, 40, 50};
//2 declararea i iniializarea matricii m
double m[2][3]={{1.1,2.2,3.3}, {11.11,22.22,33.33}};
//3
struct pers{
char nume[20]; int varsta; double salariu;
}p={"Popescu", 20, 3000000};

PROGRAMAREA ORIENTATA PE OBIECTE, CURS Autor: Diana tefnescu


30
CAPITOLUL 2 Clase i obiecte

n cazul tipurilor de date definite cu ajutorul claselor, care au date membru private, listele de
iniializare nu pot fi utilizate. Pentru a elimina aceste neajunsuri, limbajul C++ ofer
mecanismul constructorilor i al desctructorilor.

2.7.2. CONSTRUCTORI

Constructorii sunt metode speciale care folosesc la crearea i iniializarea instanelor unei
clase. Constructorii au acelai nume ca i clasa creia i aparin i sunt apelai de fiecare dat
cnd se creaz noi instane ale clasei. Constructorii asigur iniializarea corect a tuturor
variabilelor membre ale obiectelor unei clase i constituie o garanie a faptului c iniializarea
unui obiect se realizeaz o singur dat. O clas poate avea mai muli constructori (exemplul
3), care difer ntre ei prin numrul i tipul parametrilor acestora. Acest lucru este posibil
deoarece limbajul C++ permite supradefinirea (overloading) funciilor.

Suprancarcarea (supradefinirea) reprezint posibilitatea de a atribui unui nume mai multe


semnificaii, care sunt selectate n funcie de context. Practic, se pot defini funcii cu acelai
nume, dar cu liste de parametri diferite, ca numr i/sau ca tipuri de parametri. n momentul
apelului funciei, selectarea funciei adecvate se face n urma comparrii tipurilor parametrilor
efectivi cu tipurile parametrilor formali. De aceea, declararea unor funcii cu acelai nume i
acelai set de parametri este ilegal i este semnalat ca eroare la compilare.

La ntlnirea declaraiei unui obiect, se apeleaz automat un constructor al clasei respective.


La fiecare instaniere a clasei se aloc memorie pentru datele membre. Deci pentru fiecare
obiect declarat se aloc memorie pentru datele membre ale clasei. Excepie de la aceast
regul o constituie datele membru statice. Acestea figureaz ntr-un singur exemplar pentru
toate instanele clasei respective. Funciile membru exist ntr-un singur exemplar pentru toate
instanele clasei. Ordinea n care sunt apelai constructorii corespunde ordinii declarrii
obiectelor.

Proprietile constructorilor:
Constructorii au acelai nume ca i numele clasei creia i aparin;
Nu ntorc nici o valoare (din corpul lor lipsete intruciunea return <expr>; n antetul
constructorilor nu se specific niciodat - la tipul valorii returnate - cuvntul cheie void);
Constructorii unei clase nu pot primi ca parametri instane ale clasei respective, ci doar
pointeri sau referine la instanele clasei respective;
Apelul constructorului se realizeaz la declararea unui obiect;
Adresa constructorilor nu este accesibil utilizatorului;
Constructorii nu pot fi metode virtuale (capitolul 4);
n cazul n care o clas nu are nici constructor declarat de ctre programator,
compilatorul genereaz un constructor implicit, fr nici un parametru, cu lista
instruciunilor vid. Dac exist un constructor al programatorului, compilatorul nu mai
genereaz constructorul implicit (exemplul 2);
Parametrii unui constructor nu pot fi de tipul definit de clasa al crei membru este
constructorul.

Ca orice alt funcie n limbajul C++, constructorii pot avea parametri implicii, fiind numii
constructori implicii. Varianta constructorului cu parametri implicii poate fi adoptat n toate
cazurile n care constructorul nu necesit argumente. Dac toi parametrii unui constructor
sunt implicii, apelul constructorului are forma unei simple declaraii (exemplul 1).
Constructorii pot fi apelai i n mod explicit (exemplul 1). n cazul n care

PROGRAMAREA ORIENTATA PE OBIECTE, CURS Autor: Diana tefnescu


31
CAPITOLUL 2 Clase i obiecte

dorim s instaniem obiecte att iniializate, ct i neiniializate se poate folosi un constructor


implicit vid, care se va apela la instanierea obiectelor neiniializate (exemplul 3).

Exemplul1: Pentru clasa complex s-a definit un constructor cu parametri implicii; din acest
motiv s-a putut face declaraia "complex z1;". n ultima linie a programului, pentru
obiectul z4, constructorul este apelat n mod explicit.
class complex
{ double real,imag;
public: complex(double x=0, double y=0); // Constructor implicit
};

complex::complex(double x, double y)
{real=x; imag=y; }
main()
{complex z1; //z1.real=0, z1.imag=0
complex z2(1); //z2.real=1, z2.imag=0
complex z3(2,4); //z3.real=2, z3.imag=4
complex z4=complex(); //apel explicit al constructorului
}

La apelul explicit al constructorului: complex z4=complex();


Evaluarea expresiei complex() conduce la:
9 Crearea unui obiect temporar de tip punct (obiect cu o adres precis, dar inaccesibil);
9 Apelul constructorului pentru acest obiect temporar;
9 Copierea acestui obiect temporar n z4.

Exemplul2: Pentru clasa complex exist un constructor explicit, compilatorul nu mai creeaz
unul implicit.
class complex
{ double real,imag;
public:
complex(double x,double y) // funcie constructor inline
{ real=x; imag=y;}
};
main()
{complex z1(2,3);
complex z; // Eroare : nu exist constructor implicit
}

Exemplul3: Definirea unui constructor implicit vid, care se va apela la instanierea obiectelor
neiniializate.
#include<iostream.h>
class data{
int zi,luna,an;
public:
data() { } // constructor implicit vid
data(int z,int l,int a) // constructor cu parametri
{ zi=z;luna=l;an=a; }
};
main()
{data d; // apelul constructorului vid
data d1(12,11,1998); // apelul constructorului cu parametri
}
PROGRAMAREA ORIENTATA PE OBIECTE, CURS Autor: Diana tefnescu
32
CAPITOLUL 2 Clase i obiecte

2.7.2.1. Constructori cu liste de iniializare

n exemplele anterioare, constructorii iniializau membrii unui obiect prin atribuiri. Exist i
modalitatea de a iniializa membrii printr-o list de instaniere (iniializare), care apare n
implementarea constructorului, ntre antetul i corpul acestuia. Lista conine operatorul :,
urmat de numele fiecrui membru i valoarea de iniializare, n ordinea n care membrii apar
n definiia clasei.

Exemplul 1: Pentru clasa complex s-a implementat un constructor de iniializare cu list de


instaniere.
class complex {
double real,imag;
public:
complex(double x, double y); //constructor
};
complex::complex(double x, double y)
:real(x),imag(y) // List de iniializare a membrilor
{ return; }

main()
{ complex z1(1,3),z2(2,3); }
// Sau:
class complex {
double real,imag;
public:
complex(double x, double y) :real(x),imag(y) { }
//constructor cu list de iniializare
};

2.7.2.2. Constructori de copiere

Pentru o clas, se poate defini un contructor de copiere, care s permit copierea obiectelor.
Deoarece parametrii unui constructor nu pot fi de tipul definit de clasa al crei membru este,
constructorul de copiere pentru clasa cu numele cls, are, de obicei, prototipul:
<cls> (const <cls> &);
Parametrul transmis prin referin este obiectul a crui copiere se realizeaz, modificatorul de
acces const interzicnd modificarea acestuia. Constructorul de copiere poate avea i ali
parametri, care trebuie s fie implicii.
Dac programatorul nu definete un constructor de copiere, compilatorul genereaz un
asemenea constructor, implicit.
n situaiile n care un tip de date are ca membrii pointeri, este necesar implementarea unui
constructor pentru iniializare (este de dorit s se aloce dinamic memorie) i a unui
constructor de copiere.

Exemplu: Exemplul urmtor, n care se definesc tipurile de date Punct i Linie, ilustreaz
utilizarea constructorilor (cu parametri implicii, de copiere, cu liste de iniializare) definii de
programator.
#include <iostream.h>
class Punct
{public:
Punct(double _x=0.0, double _y=0.0)// Constructor cu parametri impliciti
{ x = _x; y = _y; }
PROGRAMAREA ORIENTATA PE OBIECTE, CURS Autor: Diana tefnescu
33
CAPITOLUL 2 Clase i obiecte

Punct(const Punct& p) { x = p.x, y = p.y;} //Constructor de copiere


void afiseaza(); // Metoda afiseaza
private:
double x, y; // Datele membre private (coodonatele punctului: abscisa si ordonata)
};

class Linie
{public:
Linie(const Punct& b, Punct& e) : p1(b), p2(e) {}
//Constructor cu lista initializare
void afiseaza();
private:
Punct p1, p2; //Datele membre private: cele 2 puncte care determina dreapta
};

void Punct::afiseaza()
{ cout << "(" << x << " , " << y << ")"; }
void Linie::afiseaza()
{ cout << "Linie determinata de punctele: ";
p1.afiseaza(); p2.afiseaza(); cout <<\n; }

main()
{
Punct a=(10.,15.), b=(20.,30.); a.afiseaza(); b.afiseaza();
Linie l1(a,b); l1.afiseaza(); }

2.7.3. DESTRUCTORI

Destructorii sunt metode ale claselor care acioneaz n sens invers, complementar, fa de
constructori.
Constructorii sunt folosii pentru alocarea memoriei, iniializarea datelor membru sau alte
operaii (cum ar fi, incrementarea unui contor pentru instanele clasei). Constructorul este
apelat n momentul declarrii obiectelor.
Destructorul elibereaz memoria alocat de constructori. Destructorul este apelat automat, la
ieirea din blocul n care este recunoscut acel obiect.

Proprietile destructorilor
Destructorul are acelai nume ca i clasa a cror metod este;
Numele destructorului este precedat de semnul ~;
O clas are un singur destructor;
Destructorul nu are parametri i nu returneaz nici o valoare (antetul nu conine cuvntul
cheie void, iar n corpul destructorului nu apare instruciunea return <expresie>;);
Dac programatorul nu a definit un destructor, compilatorul genereaz automat un
destructor pentru clasa respectiv;
Destructorii se apeleaz la ncheierea timpului de via a obiectelor, n ordine invers
apelurilor constructorilor;
Obiectele dinamice nu se distrug automat, deoarece doar programatorul tie cnd nu mai
este necesar un astfel de obiect.

Exerciiul 1: Se definete tipul de date Timp, care implementeaz un cronometru care


msoar timpul scurs ntre 2 evenimente (evenimente date de apelul constructorului i al
destructorului). Se folosete funcia clock din ANSI C.

PROGRAMAREA ORIENTATA PE OBIECTE, CURS Autor: Diana tefnescu


34
CAPITOLUL 2 Clase i obiecte

/* fiierul timp.h, cu definirea clasei */


#if !defined(__TIMP_H)
#define __TIMP_H
#include <time.h> // defineste tipul clock_t si CLK_TCK
#include <iostream.h>

class Timp
{public:
Timp() { start = clock();} // Constructor
~Timp() // Destructor (calculeaza si afiseaza timpul, in secunde)
{ clock_t stop = clock();
cout << "Timpul = "; cout << (stop - start)/CLK_TCK;
cout << " secunde" << \n; }
private:
clock_t start; // porneste masurarea timpului
};
#endif

/* fisierul de test, timptest.cpp, in care se utilizeaza tipul de date Timp */


#include "timp.h"
static void functie(unsigned long cont)
{ Timp t; // Declararea obiectului t, de tip Timp
for(unsigned long i = 0; i < cont; i++)
{ double a = (double)(i-1); double b = (double)(i+1);
double c = (double)(i+i); double d = a*b - c; }
}

main()
{ unsigned long val_cont; cout << "Valoare finala: ";
cin >> val_cont; functie(val_cont);
}

Observaii: Clasa Timp are data membru privat start (de tipul clock_t), constructor i
destructor. Constructorul (definit de programator), n momentul apelului (la declararea
obiectului t n funcia functie), iniializeaz data membr cu valoarea returnat de funcia
clock (deci, momentul nceperii execuiei corpului funciei). Se execut prelucrrile din
corpul funciei (calculul valorilor variabilelor a, b, c i d pentru fiecare valoare a contorului
i). La ieirea din funcie, este apelat destructorul (definit de programator) clasei Timp (se
distruge obiectul t, variabil local funciei). Astfel, n variabila stop, variabil local
destructorului, se memoreaz valoarea returnat de funcia clock (deci timpul momentului de
ncheiere a execuiei corpului funciei funcie). Diferena ntre cele 2 evenimente (nceputul
execuiei corpului funciei funcie i sfritul acesteia) este transformat n secunde i afiat.

Exerciiul 2:
S se defineasc tipul punct, cu datele membre x i y, reprezentnd abscisa i ordonata unui
punct. Operaiile care pot fi realizate asupra obiectelor de tip punct, sunt: afiare (afieaz
coordonatele unui punct), deplasare (deplaseaz un punct, noile coordonate ale punctului
fiind obinute prin adunarea unor valori transmise ca parametri, la valorile anterioare ale
coordonatelor), abscisa (returneaz valoarea abscisei), ordonata (returneaz valoarea
ordonatei). Se vor implementa, deasemenea, constructor cu parametri implicii, constructor
avnd ca parametri valorile abscisei i a ordonatei, constructor de copiere i destructor.

PROGRAMAREA ORIENTATA PE OBIECTE, CURS Autor: Diana tefnescu


35
CAPITOLUL 2 Clase i obiecte

S se defineasc tipul segment, cu datele membre A i B, de tip punct, reprezentnd


capetele unui segment (originea i vrful). Operaiile care pot fi realizate asupra obiectelor de
tip segment, sunt: afiare (afieaz coordonatele capetellor segmentului), deplasare
(translateaz un segment, deplasnd capetele acestuia cu valorile transmise ca parametri),
origine (returneaz originea segmentului), vrf (returneaz vrful segmentului). Se vor
implementa, deasemenea, constructor, constructor de copiere i destructor.
S se testeze tipurile de date punct i segment.

#include <iostream.h>
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
//CLASA PUNCT
class punct
{ double x,y;
public:
punct()
{x=0;y=0;
cout<<"Constr. implicit pentru punct("<<x<<","<<y<<")\n";}
//constructor initializare
punct(double,double);
punct(punct&); //constructor copiere
~punct(); //destructor
double abscisa(){return x;}
double ordonata(){return y;}
void afisare();
void deplasare(double,double);
};

//CLASA SEGMENT
class segment
{private:
punct A,B;
public:
segment(punct&,punct&); //constructor
segment(segment&); //constructor copiere
~segment(); //destructor
punct origine();
punct varf();
void afisare();
void translatie(double,double);
};

//METODELE CLASEI PUNCT


punct::punct(double valx,double valy)
{ x=valx;y=valy;cout<<"Constructor punct("<<x<<","<<y<<")\n";}
punct::~punct()
{cout<<"Destructor punct ("<<x<<","<<y<<")\n";}
punct::punct( punct &P)
{x=P.x;y=P.y;cout<<"Constructor copiere";
cout<<" pct ("<<x<<","<<y<<")\n";}
void punct::deplasare(double dx,double dy)
{x+=dx; y+=dy;}
void punct::afisare(){ cout<<"Punct ("<<x<<','<<y<<')';}

PROGRAMAREA ORIENTATA PE OBIECTE, CURS Autor: Diana tefnescu


36
CAPITOLUL 2 Clase i obiecte

//METODELE CLASEI SEGMENT


segment::segment(punct &A1,punct &B1)
{ A=A1;B=B1;cout<<"Constructor segment[";
A.afisare();B.afisare();cout<<"]\n";}
segment::segment(segment &AB)
{ A=AB.A; B=AB.B; cout<<"Constructor copiere segment [";
A.afisare(); B.afisare();cout<<"]\n";}
punct segment::origine()
{ return A;}
punct segment::varf()
{ return B;}
void segment::afisare()
{cout<<"[";A.afisare();cout<<','; B.afisare();cout<<"]"<<'\n';}
segment::~segment()
{ cout<<"Destructor segment [";A.afisare();
cout<<",";B.afisare(); cout<<"]\n";}
void segment::translatie(double dx,double dy)
{ A.deplasare(dx,dy); B.deplasare(dx,dy);}

main()
{ punct P(7.8,-20.4),Q(-4.82,8.897),A,B;
/*Constructor punct (7.8,-20.4) (Pentru punctul P)
Constructor punct (-4.82,8.897) (Pentru punctul Q)
Constr. implicit pentru punct(0,0)
Constr. implicit pentru punct(0,0) (pentru punctele A, B)*/
punct P3, Q3;
/* Constr. implicit pentru punct(0,0)Constr. implicit pentru punct(0,0) (pentru
punctele P3, Q3) */
segment S(P,Q);
/* Constr. implicit pentru punct(0,0)Constr. implicit pentru punct(0,0)
(pentru membrii A, B ai obiectului S, deci pentru S.A i S.B)
Constructor segment[Punct (7.8,-20.4)Punct (-4.82,8.897)] (pentru obiectul S, de tip
segment) */
segment S1(P3,Q3);
/* Constr. implicit pentru punct(0,0)
Constr. implicit pentru punct(0,0) (pentru membrii A, B ai obiectului S1, deci pentru
S1.A i S1.B)
Constructor segment[Punct (0,0)Punct (0,0)] (pentru obiectul S1, de tip segment) */
printf("Apasa un car. ptr. continuare!\n"); getch();
cout<<"Punctele:\n";
P.afisare();cout<<'\n'; Q.afisare();cout<<'\n';
P3.afisare();cout<<'\n'; Q3.afisare();cout<<'\n';
A.afisare(); cout<<'\n'; B.afisare();cout<<'\n';
cout<<"\nSegment:"; S.afisare(); cout<<'\n';
/* Punctele:
Punct (7.8,-20.4) (pentru obiectul P)
Punct (-4.82,8.897) (pentru obiectul Q)
Punct (0,0) (pentru obiectul A)
Punct (0,0) (pentru obiectul B)
Punct (0,0) (pentru obiectul P3)
Punct (0,0) (pentru obiectul Q3)
Segment:[Punct (7.8,-20.4),Punct (-4.82,8.897)] */
punct D(1,2); punct C;

PROGRAMAREA ORIENTATA PE OBIECTE, CURS Autor: Diana tefnescu


37
CAPITOLUL 2 Clase i obiecte

// Constructor punct (1,2)Constr. implicit pentru punct(0,0) (pentru punctele D, C)


C=D; //operaie de atribuire
C.afisare(); // Punct (1,2) (pentru punctul C)
getch();
punct CC=C; // Constructor copiere pct (1,2)
cout<<"In urma copierii:"; CC.afisare();
// n urma copierii:Punct (1,2) (pentru punctul CC)
cout<<"Se deplaseaza punctul CC cu valorile 10, 20. Noile coord.=";
CC.deplasare(10, 20); CC.afisare();
// Se deplaseaza punctul CC cu valorile 10, 20. Noile coord.=Punct (11,22)
cout<<"Abscisa CC="<<CC.abscisa();
cout<<" Ordonata CC="<<CC.ordonata()<<'\n';
//Abscisa CC=11 Ordonata CC=22
cout<<"Varf segment S="; (S.varf()).afisare();
/* Varf segment S=Constructor copiere pct (-4.82,8.897) (metoda varf returneaza un
punct, copiere)
Punct (-4.82, 8.897) Destructor punct (-4.82,8.897) */
cout<<"Origine segment S="; CC=S.origine();
/* Origine segment S=Constructor copiere pct (7.8,-20.4) (metoda origine returneaza
un punct, copiere) Destructor punct (7.8,-20.4) */
CC.afisare(); // Punct (-4.82, 8.897)
S1=S; //operatie de atribuire
S1.afisare();
// Punct (7.8,-20.4)[Punct (7.8,-20.4),Punct (-4.82,8.897)]
cout<<"Translatie S1 cu 100,1000. S1 translatat este:";
S1.translatie(100, 1000); S1.afisare();
/* Translatie S1 cu 100,1000.
S1 translatat este:[Punct (107.8,979.6),Punct (95.18,1008.897)] */
segment S2=S1; /* Constr. implicit pentru punct(0,0) (pentru S2.A)
Constr. implicit pentru punct(0,0) (pentru S2.B)
Constructor copiere segment [Punct (107.8,979.6)Punct (95.18,1008.897)]
Destructor segment [Punct (107.8,979.6),Punct (95.18,1008.897)]*/
cout<<"Segment S2 obtinut prin copiere:";
S2.afisare();
// Segment S2 obtinut prin copiere:[Punct (107.8,979.6),Punct (95.18,1008.897)]
cout<<"Iesire din main\n"; // Iesire din main
}

/* La ieirea din funcia main, deci la terminarea duratei de via a obiectelor, se apeleaz
automat destructorii, n ordinea invers n care au fost apelai constructorii, astfel:

Destructor segment [Punct (107.8,979.6),Punct (95.18,1008.897)] (pentru segmentul S2)


Destructor punct (95.18,1008.897) (pentru membrii B, respectiv A, ai segmentului S2: S2.B,
apoi S2.A)
Destructor punct (107.8,979.6)
Destructor punct (7.8,-20.4) (pentru CC)
Destructor punct (1,2) (pentru C)
Destructor punct (1,2) (pentru D)
Destructor segment [Punct (107.8,979.6),Punct (95.18,1008.897)] (pentru segmentul S1)
Destructor punct (95.18,1008.897) (pentru membrii B, respectiv A, ai segmentului S1: S1.B,
apoi S1.A)
Destructor punct (107.8,979.6)

PROGRAMAREA ORIENTATA PE OBIECTE, CURS Autor: Diana tefnescu


38
CAPITOLUL 2 Clase i obiecte

Destructor segment [Punct (7.8,-20.4),Punct (-4.82,8.897)] (pentru segmentul S)


Destructor punct (-4.82,8.897) (pentru membrii B, respectiv A, ai segmentului S: S.B, apoi
S.A)
Destructor punct (7.8,-20.4)
Destructor punct (0,0) (pentru punctul Q3)
Destructor punct (0,0) (pentru punctul P3)
Destructor punct (0,0) (pentru punctul B)
Destructor punct (0,0) (pentru punctul A)
Destructor punct (-4.82,8.897) (pentru punctul Q)
Destructor punct (7.8,-20.4) (pentru punctul P) */

Exerciiul evideniaz urmtoarele probleme:


1. n situaia n care o clas C1 are ca date membre obiecte ale altei clase C2 (clasa segment
are ca date membre obiecte de tipul punct), la construirea unui obiect din C1, se apeleaz
nti constructorul C2 pentru membrii (de tip C2), apoi constructorul C1.
Un astfel de exemplu l constituie declararea segmentului S: segment S(P,Q);
Se apeleaz nti constructorul implicit al clasei punct pentru membrii A i B ai
segmentului S (deci pentru S.A i S.B), apoi constructorul clasei segment (figura 2.4.). La
distrugerea obiectului din clasa C1, destructorii sunt apelai n ordinea invers
constructorilor (nti se apeleaz destructorul clasei segment - nveliul exterior, apoi
destructorul pentru membrii de tip punct).
2. S revedem secvena:
punct D(1,2); punct C; C=D;
n acest caz, se realizeaz o atribuire, membru cu membru, echivalent cu:
C.x=D.x i C.y=D.y.
3. S revedem secvena:
punct CC=C; A.x A.y
n acest caz, se apeleaz constructorul de copiere,
care creaz punctul CC prin copierea punctului 7.8 -20.4
A
C. Apelul constructorului de copiere se poate
realiza i explicit: S
B.x B.y
punct CC=punct(C);
4. Parametrii transmii
S lum ca exempluunei funcii pot
constructorul fi obiecte,
clasei segment:
B -4.82 8.897
pointeri ctre obiecte sau referine ctre obiecte.
Valoarea returnat de o funcie poate fi un obiect,
Figura 2.4. Apelul constructorilor
pointer ctre obiect sau referin ctre obiect.

n cazul constructorului clasei segment, acesta este definit astfel:


segment::segment(punct &A1,punct &B1)
{ A=A1;B=B1;cout<<"Constructor segment\n";}
Constructorul primete ca parametri referine ctre obiecte de tipul punct. Apelul
constructorului:
segment S(P, Q);
Parametrii efectivi P i Q sunt referine pentru A1 i B1 (aceleai obiecte). Ca urmare, se
apeleaz cei doi constructori implicii pentru membrii A i B ai segmentului S. n urma
operaiei de atribuire din corpul constructorului segmentului, ei sunt iniializai. Mesajele care
vor apare la declararea unui obiect al clasei segment sunt:
"Constructor pct implicit!!" (pentru membrul A al segmentului S)
"Constructor pct implicit!!" (pentru membrul B al segmentului S)
"Constructor segment" (pentru segmentului S)

PROGRAMAREA ORIENTATA PE OBIECTE, CURS Autor: Diana tefnescu


39
CAPITOLUL 2 Clase i obiecte

Constructorului puteau s i se transmit parametri prin pointeri:


segment::segment(punct *A1,punct *B1)
{ A=*A1;B=*B1;cout<<"Constructor segment\n";}
Apelul: segment S(&P, &Q);
Parametrii formali A1 i B1 sunt iniializai n momentul apelului constructorului cu adresele
punctelor P, respectiv Q. Situaia este similar celei anterioare, mesajele obinute sunt identice
celor obinute n cazul transmiterii parametrilor prin referin.

Constructorului puteau s i se transmit parametri prin valoare:


segment::segment(punct A1,punct B1)
{ A=A1;B=B1;cout<<"Constructor segment\n";}
Apelul: segment S(P, Q);
n aceast situaie, la apel, pentru parametrii formali A1 i B1 se rezerv memorie pe stiv:
obiectele locale constructorului, A1 i B1, sunt iniializate prin copiere (la transmiterea
parametrilor prin valoare, se realizeaz o copiere a parametrilor efectivi n parametrii
formali). La terminarea execuiei corpului funciei, punctele A1 i B1 sunt distruse. De aceea,
mesajele din aceast situaie, sunt:
"Constructor copiere punct!!" (pentru A1, local constructorului)
"Constructor copiere punct!!" (pentru B1, local constructorului)
"Constructor pct. implicit!!" (pentru membrul A al segmentului)
"Constructor pct. implicit!!" (pentru membrul B al segmentului)
"Constructor segment!" (pentru segmentul S)
"Destructor punct!" (pentru B1, la ieirea din constructor)
"Destructor punct!" (pentru A1, la ieirea din constructor)

Exerciiul 3: Pentru tipurile punct i segment implementate anterior, s se scrie i s se


testeze urmtorul program, n care obiectele A, B (de tip punct) i AB (de tip segment) sunt
globale (declarate n afara oricrei funcii).
Se folosesc, deasemenea, variabile locale statice.
Pentru variabilele globale (A, B, AB) i cele locale declarate explicit statice (P1 din test1,
U i V din blocul interior funciei main), se aloc memorie static. Pentru variabilele locale se
aloc memorie automatic, pe stiv.
S se urmreasc evidenieze crearea i distrugerea obiectelor statice i automatice, domeniul
de vizibilitate i timpul de via.

class punct
{ //. . . . .
};
class segment
{ //. . . . .
};
//Implementarea metodelor clasei punct
//Implementarea metodelor clasei segment

punct test1()
{ cout<<"Intrare in test1\n";
static punct P1(20,10);
P1.deplasare(1,1); cout<<"Iesire din test1\n";return P1;}
punct test2()
{ punct P1(100,100);P1.deplasare(10,20);return P1; }
punct A(1,2), B;
segment AB(A, B);

PROGRAMAREA ORIENTATA PE OBIECTE, CURS Autor: Diana tefnescu


40
CAPITOLUL 2 Clase i obiecte

main()
{cout<<"S-a intrat in main!\n"; punct E(1, 1), F, G;
F=test1(); cout<<"F="; F.afisare();
getch();G=test2();cout<<"Intrare in test1\n";cout<<"G=";
G.afisare();
{
cout<<"Intrare in blocul interior\n";
static punct U(5,2);punct C(9,9), D(5.5,6.6);
static punct V(8,3);getch();
F=test1(); cout<<"Intrare in test1\n";F.afisare();G=test2();
cout<<"Intrare in test2\n";G.afisare();
cout<<"Iesire din blocul interior\n";
}
getch();A.afisare();F.afisare();AB.afisare();AB.translatie(10, 10);
cout<<"Segment translatat:"; AB.afisare();
cout<<"Segmentul AB are originea:"; (AB.origine()).afisare();
cout<<"Segmentul AB are varful:"; (AB.varf()).afisare();
cout<<"Iesire din main()\n"; }

Exerciiul 4: Se implementeaz clasa Paralelipiped, cu datele membre Lung, Lat,


Inalt, doi constructori i metoda volum (calculeaz i afieaz volumul unui paralelipiped).

#include <iostream.h>
class Paralelipiped {
int Lung, Lat, Inalt; // date membre private
public:
// ------ constructori
Paralelipiped() { /* nimic */ } // constructor null!!!
Paralelipiped(int l1, int l2, int l3)
{ Lung = l1; Lat = l2; Inalt = l3; }
// ----- functie membra
int volum() { return Lung * Lat * Inalt; }
};

main()
{ Paralelipiped c1(7, 8, 9); // declarare obiect de tip Paralelipiped
Paralelipiped c2; // un obiect Paralelipiped fara initializare
c2 = c1; // constructor copiere implicit!!!
cout << c1.volum();cout << c2.volum(); }

Exerciiul 5: n urmtorul exerciiu se implementeaz clasa File, cu constructor, destructor


i metode de citire/scriere.

#include <stdio.h>
class File
{FILE *fp; // stream C
// ...
public:
File(const char *nume, const char *open_mode); // Constructor
~File(); // Destructor
size_t read(const size_t howmany, const size_t elem_size,
void *buffer); // Citire din fisier in buffer
size_t write(const size_t howmany, const size_t elem_size,
const void *buffer); // Scriere din buffer in fisier
};
PROGRAMAREA ORIENTATA PE OBIECTE, CURS Autor: Diana tefnescu
41
CAPITOLUL 2 Clase i obiecte

// implementarea metodelor clasei File


File::File(const char *nume, const char *open_mode)
{ fp = fopen(nume, open_mode);}
File::~File()
{ if(fp != NULL) fclose(fp);}
size_t File::read(const size_t howmany,const size_t elem_size,void
*buffer)
{if(fp != NULL)return(fread(buffer, elem_size, howmany, fp));
else return 0;}
size_t File::write(const size_t howmany,const size_t elem_size,const
void *buffer)
{if(fp != NULL)return(fwrite(buffer, elem_size, howmany, fp));
else return 0;}

/* functia de test: copierea continutului fisierului sursa in fisierul destinatie */


main(void)
{char *Nume_sursa, *Nume_destinatie;
printf("Nume fisier din care se citeste:");scanf("%s", Nume_sursa);
printf("Nume fisier din care se citeste:");
scanf("%s", Nume_destinatie);
File f1(Nume_sursa, "rb"); //deschiderea fisierelor
File f2(Nume_destinatie, "wb");
char buffer[512]; size_t count;
// Citire dintr-un fisier si scriere in altul
while((count = f1.read(512, sizeof(char), buffer)) != 0)
{ f2.write(count, sizeof(char), buffer); }
}

Exerciiul 6: Se implementeaz clasa Debug, pentru depanarea programalor C++.


#include <stdio.h>
#include <stdarg.h>

class Debug
{ private:
unsigned int indent();
void separator();
static unsigned int debug_level;
static unsigned int debug_on;
static unsigned int indent_prin;
static unsigned int marime_linie;
enum {off = 0, on = 1};
public:
Debug(const char *label = " ");//constructor
~Debug();//destructor
void afiseaza(const char *format, ...);
};

// functii inline
inline Debug::~Debug() //destructorul
{ debug_level--;
separator(); }
// implementarea metodelor
Debug::Debug(const char *label)
{ if(debug_on)
{ int i; separator(); (void) indent();

PROGRAMAREA ORIENTATA PE OBIECTE, CURS Autor: Diana tefnescu


42
CAPITOLUL 2 Clase i obiecte

fprintf(stderr, "%s\n", label);


}
debug_level++;
}
//metoda pentru afisarea mesajelor la depanare
void Debug::afiseaza(const char *format, ...)
{ if(debug_on)
{(void) indent(); va_list argp; va_start(argp, format);

fprintf(stderr, format, argp);


}
}
// metoda care indenteaza linia in functie de debug_level. Returneaza nr. de spatii indentate
unsigned int Debug::indent()
{ int i;
unsigned int num_spaces = debug_level*indent_prin;
for(i = 0; i < num_spaces; i++) fputc(' ', stderr);
return(num_spaces);
}
// Deseneaza separatorul pentru identificarea nivelului de depanare (debug level)
void Debug::separator()
{ if(debug_on)
{unsigned int i;
for(i=indent();i<marime_linie;i++)
fputc('-', stderr);
fputc('\n', stderr);
}
}

// Testarea clasei Debug


unsigned int Debug::debug_level = 0; // Initializarea debug_level cu 0
unsigned int Debug::debug_on = Debug::on; // Initializarea debug_on cu "on"
unsigned int Debug::marime_linie=55; // Setarea nr-lui de caractere pe line la 55
unsigned int Debug::indent_prin = 4; // Indentare cu 4 spatii pentru fiecare nivel

// Functie recursiva pentru calculul factorialului


unsigned long factorial(int n)
{ Debug dbg("factorial");
dbg.afiseaza("argument = %d\n", n);
if(n == 1) return 1;
else return n*factorial(n-1); }
// Testarea
main()
{ Debug dbg("main");
unsigned long n = factorial(4);
dbg.afiseaza("result = %ld\n", n); }

2.8. TABLOURI DE OBIECTE


Obiectele de acelai tip pot fi grupate n tablouri. Dac un tablou este declarat fr a fi
iniializat, pentru construirea elementelor sale se apeleaz constructorul implicit. Elementele
unui tablou pot fi iniializate i cu ajutorul constructorilor cu parametri.

PROGRAMAREA ORIENTATA PE OBIECTE, CURS Autor: Diana tefnescu


43
CAPITOLUL 2 Clase i obiecte

Exemplul 1: Fie clasele punct i segment implementate anterior.


class punct{ //
};
class segment{ //
};
//implementarea metodelor claselor punct si segment
main()
{punct P(7, -7), Q(-8, 8);
punct PC=P, QC=Q;
punct V[3];
//apelul constructorului implicit pentru fiecare din cele 3 elemente ale vectorului V
punct V1[2]={P, Q};
//apelul constructorului de copiere pentru elementele V1[0] si V1[1]
punct V2[2]={punct(10,10), punct(100,100)};
//apelul constructorului cu parametri pentru fiecare din cele 2 elemente, V2[0] si V2[1]
segment SV[2];
/* EROARE: deoarece exista un constructor cu parametri, nu se genereaza automat
constructorul implicit */
segment SV[2]={segment(PC, P), segment(QC, Q)};
segment SV[2]={segment(punct(5,5), punct(55,55));
segment (punct(10,10), punct(100,100))};
}

Exemplul 2: S se urmreasc i s se explice rezultatele execuiei.

#include <iostream.h>
class dreptunghi {
int Lung;
int Lat;
public:
dreptunghi(void); //Constructor
void setare(int nou_Lung, int nou_Lat);
int calcul_arie(void);
};

dreptunghi::dreptunghi(void) //implementarea constructorului


{ Lung = 8; Lat = 8; cout<<"Apel constructor";}
// Metoda care seteaza dimensiunile dreptunghiului
void dreptunghi::setare(int nou_Lung, int nou_Lat)
{ Lung = nou_Lung; Lat = nou_Lat;}
int dreptunghi::calcul_arie(void)
{ return (Lung * Lat);}

main()
{dreptunghi mic, mediu, mare, vect[4]; /* se apeleaza constructorul pentru
obiectele mic, mediu, mare si pentru fiecare dintre cele 4 elemente ale vectorului vect */
mic.setare(5, 7);
mare.setare(15, 20);
for (int index = 1 ; index < 4 ; index++) /* pentru vect[0] datele
membre Lung si Lat raman cu valorile 8 si 8 */
vect[index].setare(index + 10, 10);
cout<<"Aria dreptunghiului mic este "<< mic.calcul_arie()<< "\n";
cout<<"Aria dreptunghiului mediu e "<<mediu.calcul_arie()<<"\n";
cout<<"Aria dreptunghiului mare e "<< mare.calcul_arie()<<"\n";

PROGRAMAREA ORIENTATA PE OBIECTE, CURS Autor: Diana tefnescu


44
CAPITOLUL 2 Clase i obiecte

for (index = 0 ; index < 4 ; index++){


cout << "Ariile elementului de indice "<<index;
cout<<" din vector=" <<vect[index].calcul_arie() << "\n";}
}

Exemplul 3: S se urmreasc i s se explice rezultatele execuiei.


#include <iostream.h>
#include <conio.h>

class CommandSet
{private:
enum {helpfunc = 0, increase = 1, decrease = 2};
public:
void help(){cout << "Help!" << '\n';}
void nohelp(){cout << "No Help!" << '\n';}
};

void (CommandSet::*f_help)() = CommandSet::help;


//declararea pointerului catre functie f_help; prin atribuire, acesta primeste adresa de inceput
a functiei help.

main()
{ CommandSet set1;//declararea obiectului set1, de tip CommandSet
//apelul metodei help, pentru obiectul set1, prin intermediul pointerului catre functie
(set1.*f_help)();
f_help = CommandSet::nohelp;// noua valoare a pointerului f_help
//apelul metodei nohelp, pentru obiectul set1, prin intermediul pointerului catre functie
(set1.*f_help)();
getch(); }

2.9. FUNCII PRIETENE


Funciile prietene (friend) sunt funcii ne-membre ale unei clase, care au acces la datele
membre private ale clasei. Funciile prietene ale unei clase trebuie precizate n definiia clasei.
n acest sens, prototipurile unor astfel de funcii sunt precedate de cuvntul cheie friend.
Spre deosebire de funciile membre, funciile prietene ale unei clase nu posed pointerul
implicit this. De aceea, deosebirea esenial ntre dou funcii care realizeaz aceleai
prelucrri, o funcie membr i o funcie prieten, const n faptul c funcia prieten are un
parametru n plus fa de funcia membru.

Observaie: Nici constructorii, nici destructorii nu pot fi funcii prietene ale unei clase.

O funcie poate fi n acelai timp funcie membr a unei clase i funcie prieten a altei clase.
n exemplul urmtor, f1 este funcie membr a clasei cls1 i funcie prieten a clasei cls2.

Exemplu:
class cls1{ // . . .
int f1(int, char); // f1 - metod a clasei cls1
// . . .
};

PROGRAMAREA ORIENTATA PE OBIECTE, CURS Autor: Diana tefnescu


45
CAPITOLUL 2 Clase i obiecte

class cls2{ //. . .


friend int cls1::f1(int, char); // f1 - prieten a clasei cls2
//. . .
};

n cazul n care se dorete ca toate funciile membre ale unei clase s aib acces la membrii
privai ai altei clase (s fie funcii prietene), prima clas poate fi declarat clasa prieten
pentru cea de-a doua clas. n exemplul urmtor, clasa cls1 este clasa prieten a clasei
cls2.

Exemplu:
class cls1;
class cls2{ //. . .
friend cls1; // clasa cls1 este clas prieten a clasei cls2
//. . .
};

Observaie: Relaia de clasa prieten nu este tranzitiv. Astfel, dac clasa cls1 este clasa
prieten a clasei cls2, iar clasa cls2 este clas prieten a clasei cls3, aceasta nu implic
faptul c, cls1 este clas prieten pentru cls3.

2.10. NTREBRI I PROBLEME


NTREBRI

1. Cnd acioneaz constructorul unei 14. Ce sunt funciile inline?


clase? 15. Constructorii unei clase pot primi ca
2. Cnd acioneaz destructorul unei clase? parametri instane ale clasei respective?
3. Cnd este absolut necesar definirea unui Dac da, n ce condiii?
constructor de copiere? 16. Cine impune comportamentul unui
4. Cnd se justific utilizarea funciilor obiect?
inline? 17. Cum se aloc memoria pentru datele
5. Caracteristicile destructorului unei clase. membre nestatice n momentul declarrii
6. Care este utilitatea motenirii? mai multor obiecte din aceeasi clas?
7. Care sunt deosebirile ntre o funcie 18. Deosebiri ntre stucturi i clase.
membr a unei clase i o functie prieten 19. Enumerati facilitile oferite de
a unei clase? programarea orientat obiect.
8. Ce fel de metode pot aciona asupra 20. Explicai conceptul de ncapsulare a
datelor membre statice ale unei clase? datelor.
9. Ce funcii au acces la membrii privai ai 21. Prototipul constructorului de copiere.
unei clase? 22. Explicai n cteva cuvinte ce este
10. Ce operator permite referirea unui motenirea multipl.
membru al structurii ? 23. Explicai n cteva cuvinte ce este
11. Ce observaie avei n legtur cu motenirea.
metodele definite n interiorul clasei i 24. Niveluri de acces la membrii i metodele
funciile inline? unei clase.
12. O clas poate fi prieten a altei clase ? 25. Cum se declar funciile prietene?
Dac da, ce nseamn acest lucru? 26. Prin ce se caracterizeaz datele membre
13. Ce sunt destructorii ? statice?

PROGRAMAREA ORIENTATA PE OBIECTE, CURS Autor: Diana tefnescu


46
CAPITOLUL 10 Clase i obiecte

27. Prin ce se realizeaz comunicarea ntre 31. Nici funciile prietene, nici metodele
obiectele unei clase? statice ale unei clase nu primesc ca
28. O clas poate avea mai muli argument implicit pointerul this.
desctructori? Dac da, n ce condiii? Explicai care sunt, totui, diferenele
29. Operatorul :: i rolul su.Ce sunt dintre ele.
funciile prietene? 32. Ce sunt clasele?
30. Ce este o metod? 33. Ce sunt constructorii implicii?

PROBLEME

1. Completai tipul de date complex, cu funciile (membre sau prietene) care vor realiza
urmtoarele operaii: Adunarea unei date de tip complex cu o dat de tip real; scderea a
dou date de tip complex; scderea unui real dintr-un complex; mprirea a dou date de
tip complex; nmulirea unui real cu un complex; ridicarea la o putere ntreag a unei date
de tip complex; compararea a dou date de tip complex.

2. S se scrie un program care citete cte dou date de tip complex, pn la ntlnirea
perechii de date (z1=0+i*0, z2=0+i*0). Pentru fiecare pereche de date, s se afieze suma,
diferena, produsul i ctul.

3. S se scrie un program care citete datele a, b, c de tip complex, rezolv i afieaz


rdcinile ecuaiei de gradul doi: ax 2 +bx+c=0.

4. Care sunt greelile din urmtoarele secvene?


a) class ex1{
char *nume; int lungime;
void init (char *s, int l)
{strcpy(nume, s); lungime=l;}
};
main()
{ex1 A; A.init("teava", 20);}

b) union numar{
private:
char exponent, mantisa[3];
public:
char exp();
};

c) class complex{
int real, imag;
complex (int x, int y)
{real=x; imag=y;}
};
main()
{complex Z(20, 30); }

5. S se analizeze urmtoarele secvene de cod. Pentru fiecare secven corect s se


specifice rezultatul execuiei. Pentru secvenele incorecte, s se identifice sursele erorilor.

47
CAPITOLUL 10 Clase i obiecte

a) #include <iostream.h>
class fractie{
int nrt, nmt;
void afis_fractie( );
};
void afis_fractie( )
{cout<<nrt<<"/"<<nmt<<'\n';}
main()
{fractie f1; f1.afis_fractie();}

b) #include <iostream.h>
class fractie{
int nrt, nmt;
void afis_fractie( );
};
protected: void afis_fractie( )
{cout<<nrt<<"/"<<nmt<<'\n';}
main( )
{fractie f1(4,7); f1.afis_fractie();}

c) #include <iostream.h>
class fractie{
int nrt, nmt;
public: fractie(int, int ); };
fractie( int n1, int n2)
{nrt=n1; nmt=n2;}
main( )
{fractie f1; }

d) #include <iostream.h>
#include <math.h>
class complex{
double re, im;
double modul_complex();
};
double complex::modul_complex()
{return sqrt(re*re+im*im;}
main()
{complex x1(3,4); cout<<x1.modul_complex();}

48

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