Documente Academic
Documente Profesional
Documente Cultură
Laborator II
Adrian Li / Ovidiu Grigore
2015
Scopul laboratorului
Laboratorul II al materiei Programare Obiect-Orientat are ca scop aprofundarea claselor i definirea constructorilor, destructorului i a operatorului de
copiere.
n acest laborator se parcurg urmtoarele puncte:
namespace-ul standard (std)
pointerul this
constructorul implicit
constructorul cu variabile
destructorul
constructorul de copiere
operatorul de copiere
Desfurarea lucrrii
n C++ apare conceptul de namespace. Acesta este o grupare de clase, variabile, funcii, obiecte, etc., folosit n special pentru a evita folosirea numelor
diferite. Nu vom studia foarte tare acest aspect, ns vom folosi librria iostream, care este organizata n astfel de namespace-uri. Cel pe care-l vom folosi
se numete namespace-ul standard.
1
#i n c l u d e <i o s t r e a m >
2
3
4
5
6
7
i n t main ( )
{
s t d : : c o u t << " Afisam un mesaj " << s t d : : e n d l ;
system ( " pause " ) ;
}
n exemplul de mai sus vrem sa folosim obiectele cout i endl, dar acestea
sunt declarate n contextul namespace-ului std. De aceea trebuie s le apelam
ntotdeauna cu std:: nainte.
Acest lucru se poate evita, specificndu-i compilatorului c vrem s folosim
namespace-ul std n mod implicit: using namespace std;, ca n exemplul de
mai jos:
1
2
#i n c l u d e <i o s t r e a m >
u s i n g namespace s t d ;
3
4
5
6
7
8
i n t main ( )
{
c o u t << " Afisam un mesaj " << e n d l ;
system ( " pause " ) ;
}
Practic, n toate programele pe care le vom crea mpreuna vom include librria
iostream i vom folosi n mod implicit namespace-ul std.
2.1
Pointerul *this
#i n c l u d e <i o s t r e a m >
u s i n g namespace s t d ;
3
4
5
6
7
8
c l a s s Exemplu
{
int a ;
public :
int b;
v o i d set_a ( i n t a )
{
t h i s >a = a ;
}
10
11
12
13
14
void a f i s ( )
{
c o u t << " a = " << a << e n d l ;
c o u t << "b = " << b << e n d l ;
}
15
16
17
18
19
20
};
21
22
23
24
25
26
27
28
29
i n t main ( )
{
Exemplu S ;
S . set_a ( 3 ) ;
S . b = 5;
S . a f i s () ;
system ( " pause " ) ;
}
Practic, pointerul this este folosit pentru a putea accesa membri ai clasei care
au acelai nume cu membri ai funciilor. Atenie, this este un pointer. Asta
nseamn c trebuie apelat fie prin operatorul ->, fie prin valoare i operatorul
.(punct): this->membru fie (*this).membru.
Not. De acum nainte vom folosi pointerul this de fiecare dat cnd accesm
membri ai clasei, ca s nu i ncurcm cu alte variabile care au acelai nume.
2.2
Constructorul implicit
#i n c l u d e <i o s t r e a m >
u s i n g namespace s t d ;
3
4
5
c l a s s Persoana
{
6
7
8
public :
c h a r nume [ 5 0 ] ;
int varsta ;
Persoana ( )
{
s t r c p y ( t h i s >nume , " n e d e f i n i t " ) ;
t h i s >v a r s t a = 0 ;
}
10
11
12
13
14
15
void a f i s ( )
{
c o u t << t h i s >nume << " a r e " << t h i s >v a r s t a << " a n i " << e n d l
;
}
16
17
18
19
20
};
21
22
23
24
25
i n t main ( )
{
Persoana P ;
P . a f i s ( ) ; // n e d e f i n i t a r e 0 a n i
26
27
28
29
30
n exemplul de mai sus, avem clasa Persoana ce are dou variabile - nume i
varsta - un constructor implicit i o funcie de afiare. Obiectul P, declarat la
linia 24, va apela constructorul n momentul declarrii. Pn s fie apelat constructorul, variabilele nume i varsta aveau valori aleatoare, dar constructorul
le iniializeaz. Afind obiectul, vom confirma acest lucru.
2.3
Constructorul cu parametri
Constructorul cu parametri este similar constructorului implicit, dar are i parametri de iniializare. Exemplul urmtor conine un constructor cu parametri.
1
2
#i n c l u d e <i o s t r e a m >
u s i n g namespace s t d ;
3
4
5
6
7
8
c l a s s Persoana
{
public :
c h a r nume [ 5 0 ] ;
int varsta ;
9
10
11
12
13
14
Persoana ( c h a r nume , i n t v a r s t a )
{
s t r c p y ( t h i s >nume , nume ) ;
t h i s >v a r s t a = v a r s t a ;
}
15
16
17
void a f i s ( )
{
c o u t << t h i s >nume << " a r e " << t h i s >v a r s t a << " a n i " << e n d l
;
18
19
20
};
21
22
23
24
25
i n t main ( )
{
Persoana P( " D a n i e l a " , 2 5 ) ;
P. a f i s () ;
26
27
28
29
30
Totui, exemplul de mai sus nu este cel mai bun pentru uz general, deoarece clasa
Persoana nu are definit un constructor implicit. Din aceast cauza nu se poate
declara un obiect prin sintaxa: Persoana D;. Mesajul afiat de compilator este
c nu avem declarat constructor implicit. Acest lucru poate fi util n momentul
n care vrem neaprat s nu se poat crea obiecte neiniializate sau iniializate
implicit.
Not. O clas poate avea mai muli constructori, inclusiv mai muli constructori cu parametri, dac aceti parametri difer. C++ ofer posibilitatea suprancrcrii funciilor (i implicit a constructorilor) dac programatorul are
nevoie. Un exemplu de suprancrcare este dac creem o funcie de afiare numit afis(int a) care afieaz numere ntregi, mai putem crea i alte funcii
numite tot afis(...) dar care au ali parametri. Ex: afis(double x) pe care o
facem s afieze un double, afis(int a, double x) care poate afia un int i un
double, etc.
Exemplul de mai jos este unul complex, avnd un constructor implicit i mai
muli constructori cu parametri. ncepnd cu linia 10 este declarat constructorul
implicit, la linia 16 este declarat primul constructor cu parametri i la linia 22
este declarat al 2lea constructor cu parametri.
1
2
#i n c l u d e <i o s t r e a m >
u s i n g namespace s t d ;
3
4
5
6
7
8
c l a s s Persoana
{
public :
c h a r nume [ 5 0 ] ;
int varsta ;
9
10
11
12
13
14
Persoana ( )
{
s t r c p y ( t h i s >nume , " n e d e f i n i t " ) ;
t h i s >v a r s t a = 0 ;
}
15
16
17
18
Persoana ( c h a r nume )
{
s t r c p y ( t h i s >nume , nume ) ;
t h i s >v a r s t a = 0 ;
19
20
21
Persoana ( c h a r nume , i n t v a r s t a )
{
s t r c p y ( t h i s >nume , nume ) ;
t h i s >v a r s t a = v a r s t a ;
}
22
23
24
25
26
27
void a f i s ( )
{
c o u t << t h i s >nume << " a r e " << t h i s >v a r s t a << " a n i " << e n d l
;
}
28
29
30
31
32
};
33
34
35
36
37
i n t main ( )
{
Persoana P ;
P. a f i s () ;
38
39
40
41
42
43
44
n exemplul de mai jos nuanm una dintre cele mai importante funcii ale
constructorului, i anume alocarea dinamic de memorie. Acesta este un bun
exemplu de cum trebuie scris o clas care folosete memorie dinamic, i din
punct de vedere al constructorilor i din punct de vedere al afirii (se verific
daca numele este NULL sau nu).
1
2
#i n c l u d e <i o s t r e a m >
u s i n g namespace s t d ;
3
4
5
6
7
8
c l a s s Persoana
{
public :
c h a r nume ;
int varsta ;
9
10
11
12
13
14
Persoana ( )
{
t h i s >nume = NULL;
t h i s >v a r s t a = 0 ;
}
15
16
17
18
19
20
21
22
23
Persoana ( c h a r nume , i n t v a r s t a )
{
t h i s >nume = new c h a r [ s t r l e n ( nume ) + 1 ] ;
i f ( t h i s >nume == NULL)
{
c o u t << " E r o a r e l a a l o c a r e " << e n d l ;
exit (0) ;
}
s t r c p y ( t h i s >nume , nume ) ;
t h i s >v a r s t a = v a r s t a ;
24
25
26
27
void a f i s ( )
{
i f ( t h i s >nume != NULL)
c o u t << t h i s >nume << " a r e " << t h i s >v a r s t a << " a n i " <<
endl ;
else
c o u t << " O b i e c t u l e s t e n e i n i t i a l i z a t " << e n d l ;
}
28
29
30
31
32
33
34
35
};
36
37
38
39
40
i n t main ( )
{
Persoana P ;
P. a f i s () ;
41
42
43
44
45
46
2.4
Destructorul
#i n c l u d e <i o s t r e a m >
u s i n g namespace s t d ;
3
4
5
6
7
8
c l a s s Persoana
{
public :
c h a r nume ;
int varsta ;
9
10
11
12
13
14
Persoana ( )
{
t h i s >nume = NULL;
t h i s >v a r s t a = 0 ;
}
15
16
Persoana ( c h a r nume , i n t v a r s t a )
17
18
19
20
21
22
23
24
25
26
27
~Persoana ( ) // d e s t r u c t o r
{
i f ( t h i s >nume != NULL)
d e l e t e [ ] t h i s >nume ;
}
28
29
30
31
32
33
void a f i s ( )
{
i f ( t h i s >nume != NULL)
c o u t << t h i s >nume << " a r e " << t h i s >v a r s t a << " a n i " <<
endl ;
else
c o u t << " O b i e c t u l e s t e n e i n i t i a l i z a t " << e n d l ;
}
34
35
36
37
38
39
40
41
};
42
43
44
45
46
i n t main ( )
{
Persoana P ;
P. a f i s () ;
47
48
49
50
2.5
Constructorul de copiere
c l a s s Persoana
{
...
};
5
6
7
8
9
10
11
12
i n t main ( )
{
Persoana P ;
// c o n s t r u c t o r i m p l i c i t
Persoana C = P ; // c o n s t r u c t o r de c o p i e r e
Persoana D;
// c o n s t r u c t o r i m p l i c i t
D = P;
// o p e r a t o r de c o p i e r e
}
#i n c l u d e <i o s t r e a m >
u s i n g namespace s t d ;
3
4
5
6
7
8
c l a s s Persoana
{
public :
c h a r nume ;
int varsta ;
9
10
11
12
13
14
Persoana ( )
{
t h i s >nume = NULL;
t h i s >v a r s t a = 0 ;
}
15
16
17
18
19
20
21
22
23
24
25
26
Persoana ( c h a r nume , i n t v a r s t a )
{
t h i s >nume = new c h a r [ s t r l e n ( nume ) + 1 ] ;
i f ( t h i s >nume == NULL)
{
c o u t << " E r o a r e l a a l o c a r e " << e n d l ;
exit (0) ;
}
s t r c p y ( t h i s >nume , nume ) ;
t h i s >v a r s t a = v a r s t a ;
}
27
28
29
30
31
32
~Persoana ( )
{
i f ( t h i s >nume != NULL)
d e l e t e [ ] t h i s >nume ;
}
33
34
35
36
37
38
39
40
41
42
s t r c p y ( t h i s >nume , X. nume ) ;
t h i s >v a r s t a = X. v a r s t a ;
43
44
45
46
void a f i s ( )
{
i f ( t h i s >nume != NULL)
c o u t << t h i s >nume << " a r e " << t h i s >v a r s t a << " a n i " <<
endl ;
else
c o u t << " O b i e c t u l e s t e n e i n i t i a l i z a t " << e n d l ;
}
47
48
49
50
51
52
53
54
};
55
56
57
58
59
i n t main ( )
{
Persoana P ;
P. a f i s () ;
60
61
62
63
Persoana D = C ;
D. a f i s ( ) ;
64
65
66
2.6
Operatorul de copiere
#i n c l u d e <i o s t r e a m >
u s i n g namespace s t d ;
3
4
5
6
7
8
c l a s s Persoana
{
public :
c h a r nume ;
int varsta ;
9
10
11
12
13
14
Persoana ( )
{
t h i s >nume = NULL;
t h i s >v a r s t a = 0 ;
}
15
16
17
18
19
20
21
22
23
24
25
26
Persoana ( c h a r nume , i n t v a r s t a )
{
t h i s >nume = new c h a r [ s t r l e n ( nume ) + 1 ] ;
i f ( t h i s >nume == NULL)
{
c o u t << " E r o a r e l a a l o c a r e " << e n d l ;
exit (0) ;
}
s t r c p y ( t h i s >nume , nume ) ;
t h i s >v a r s t a = v a r s t a ;
}
27
28
29
30
31
32
~Persoana ( )
{
i f ( t h i s >nume != NULL)
d e l e t e [ ] t h i s >nume ;
}
33
34
35
36
37
38
39
40
41
42
s t r c p y ( t h i s >nume , X. nume ) ;
t h i s >v a r s t a = X. v a r s t a ;
43
44
45
46
47
48
49
50
51
52
Persoana& o p e r a t o r =( c o n s t Persoana& X)
{
i f ( t h i s != &X)
{
i f ( t h i s >nume != NULL)
d e l e t e [ ] t h i s >nume ;
// o p e r a t o r u l de c o p i e r e
53
54
55
56
11
57
58
}
s t r c p y ( t h i s >nume , X. nume ) ;
t h i s >v a r s t a = X. v a r s t a ;
59
60
61
62
63
return this ;
64
65
66
void a f i s ( )
{
i f ( t h i s >nume != NULL)
c o u t << t h i s >nume << " a r e " << t h i s >v a r s t a << " a n i " <<
endl ;
else
c o u t << " O b i e c t u l e s t e n e i n i t i a l i z a t " << e n d l ;
}
67
68
69
70
71
72
73
74
};
75
76
77
78
79
i n t main ( )
{
Persoana P ;
P. a f i s () ;
80
81
82
83
Persoana D = C ;
D. a f i s ( ) ;
84
85
86
P = D;
P. a f i s () ;
87
88
89
Probleme
1. Creai clasa Persoana care s conin *nume i varsta. n main()
creai un vector de pointeri-obiecte de tip Persoana, dup care citii
de la tastatur un numr N de astfel de obiecte alocate dinamic.
12
2. Creai clasa de la exerciiul de mai sus, dup care creai cteva obiecte cu
acest clas, alocate unele static altele dinamic. Distrugei apoi o parte din
obiectele alocate dinamic. Gsii o metod pentru a numra n program
cte obiecte Persoana au fost create n total, i cte obiecte Persoana
mai sunt existente la un moment dat.
3. Creai o clas numit Persoana care s conin urmtorii membri:
*nume
*prenume
anul, luna i ziua naterii
serie i numr carte de identitate
Construii apoi pentru aceast clas urmtoarele metode (funcii):
constructor implicit
constructor cu parametri (cel puin 2 constructori)
constructor de copiere
destructor
operator de copiere
funcie de afiare ( afis() )
funcie ce calculeaz vrsta: int varsta();
funcie de afiare cu parametru dac s afieze i vrsta sau nu (
afis(int afis_varsta) )
Creai astfel obiecte statice i dinamice de tip Persoana pentru a exemplifica i a demonstra c programul funcioneaz corect.
13