Documente Academic
Documente Profesional
Documente Cultură
Laborator III
Adrian Li / Ovidiu Grigore
2015
Scopul laboratorului
n Laboratorul III al materiei Programare Obiect-Orientat continu laboratorul II prin definirea/suprancrcarea operatorilor i introduce conceptul de
funcii friend.
n acest laborator se parcurg urmtoarele puncte:
operatori aritmetici: +, -, *, /, ~, etc.
operatori de comparaie: ==, !=, <, >, >=, <=
operatorul de cast
operatorul subscript [ ]
clasele istream si ostream i obiectele cin i cout
funcii friend
operatorii i
Desfurarea lucrrii
delete
=
&=
>=
()
*
<
|=
&&
[]
/
>
||
%
+=
++
^
-=
=
&
*=
=
,
|
/=
==
->*
~
~=
~=
->
t i p _ r e t u r n a t o p e r a t o r #( p a r a m e t r i )
{
// o p e r a t i i
}
#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
9
10
11
12
13
c l a s s Complex
{
double re ;
d o u b l e im ;
public :
Complex ( )
{
t h i s >r e = 0 ;
t h i s >im = 0 ;
}
14
Complex ( d o u b l e re , d o u b l e im )
{
t h i s >r e = r e ;
t h i s >im = im ;
}
15
16
17
18
19
20
void a f i s ( )
{
c o u t << t h i s >r e << "+" << t h i s >im << " i " << e n d l ;
}
21
22
23
24
25
};
26
27
28
29
i n t main ( )
{
Complex A;
Complex B( 2 , 3 ) ;
30
31
A. a f i s ( ) ;
B. a f i s ( ) ;
32
33
34
//0+0 i
//2+3 i
2.1
Operatori aritmetici
Prima operaie care o vom implementa va fi operaia de adunare, dat de operatorul +. Forma acesteia este dat n exemplul de mai jos, iar toate celelalte
operaii aritmetice ce implic doi termeni (- * /) sunt similare.
1
2
3
4
5
6
7
n codul de mai sus, se ncepe la linia 1 cu declararea funciei operator+. Operatorul + este un operator ntre doi termeni. Primul termen este chiar obiectul
asupra cruia scriem operatorul (obiectul this). Al 2lea obiect este tot de tip
Complex, si este dat de T2. Funcia va returna Complex deoarece din adunarea a dou numere complexe rezult tot un numr complex. La linia 3 declarm
un nou obiect numit Rezultat, obiect care va ine minte rezultatul adunrii. Liniile 4 i 5 execut operaia de adunare efectiv (adunarea numerelor complexe)
iar linia 6 returneaz rezultatul obinut. Codul complet al acestui program
funcional, precum i exemplificarea operatorului este urmtorul.
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
9
10
11
12
13
c l a s s Complex
{
double re ;
d o u b l e im ;
public :
Complex ( )
{
t h i s >r e = 0 ;
t h i s >im = 0 ;
}
14
15
16
17
18
19
Complex ( d o u b l e re , d o u b l e im )
{
t h i s >r e = r e ;
t h i s >im = im ;
}
20
21
22
23
24
R e z u l t a t . im = t h i s >im + T2 . im ;
return Rezultat ;
25
26
27
28
void a f i s ( )
{
c o u t << t h i s >r e << "+" << t h i s >im << " i " << e n d l ;
}
29
30
31
32
33
};
34
35
36
37
38
39
i n t main ( )
{
Complex A( 5 , 1 ) ;
Complex B( 2 , 3 ) ;
Complex C ;
40
C = A + B;
41
42
A. a f i s ( ) ; //5+1 i
B . a f i s ( ) ; //2+3 i
C . a f i s ( ) ; //7+4 i
43
44
45
46
return Rezultat ;
6
7
8
9
10
11
12
13
14
15
Complex o p e r a t o r +( c o n s t d o u b l e &T2 )
{
Complex R e z u l t a t ;
R e z u l t a t . r e = t h i s >r e + T2 ;
R e z u l t a t . im = t h i s >im ;
return Rezultat ;
}
#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
9
10
11
12
13
c l a s s Complex
{
double re ;
d o u b l e im ;
public :
Complex ( )
{
t h i s >r e = 0 ;
t h i s >im = 0 ;
}
14
Complex ( d o u b l e re , d o u b l e im )
{
t h i s >r e = r e ;
t h i s >im = im ;
}
15
16
17
18
19
20
21
22
23
24
25
26
27
28
Complex o p e r a t o r +( c o n s t d o u b l e &T2 )
{
Complex R e z u l t a t ;
R e z u l t a t . r e = t h i s >r e + T2 ;
R e z u l t a t . im = t h i s >im ;
return Rezultat ;
}
29
30
31
32
33
34
35
36
void a f i s ( )
{
c o u t << t h i s >r e << "+" << t h i s >im << " i " << e n d l ;
}
37
38
39
40
41
};
42
43
44
45
i n t main ( )
{
Complex A( 5 , 1 ) ;
Complex B( 2 , 3 ) ;
Complex C ;
46
47
48
A. a f i s ( ) ; //5+1 i
B . a f i s ( ) ; //2+3 i
49
50
51
C = A + B;
C . a f i s ( ) ; //7+4 i
52
53
54
C = C + 3;
C . a f i s ( ) ; //10+4 i
55
56
57
C = A + B + C + 10;
C . a f i s ( ) ; //27+8 i
58
59
60
La linia 52 se poate observa prima operaie de adunare, executat de ctre primul operator+. La lina 55 putem observa operaia de adugare executat de
ctre al doilea operator+. La linia 58 este puin mai complex: ntre A i B se
execut primul operator, ntre B i C se execut tot primul operator, iar ntre
C i 10 se execut al doilea operator. Una din probleme de la sfrit v cere s
demonstrai ordinea executrii.
Programul urmtor conine operatorul - i operatorul tild (~). Operaiile * i
/ (nmulire i mprire) se pot implementa similar, folosind funciile matematice necesare. Operatorul tild este operatorul care n mod tradiional, aplicat
unui numr binar returneaz inversul acestuia (0 devine 1 i 1 devine 0 pentru
fiecare bit n parte). n exemplul nostru acesta a fost suprancrcat pentru a
calcula conjugatul complex al numrului. Sintaxa acestuia este diferit (nu
are parametri) deoarece este un operator unar (are un singur argument) spre
deosebire de +, -, etc care sunt operatori binari (ntre doi termeni).
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
9
10
11
12
13
c l a s s Complex
{
double re ;
d o u b l e im ;
public :
Complex ( )
{
t h i s >r e = 0 ;
t h i s >im = 0 ;
}
14
15
16
17
18
19
Complex ( d o u b l e re , d o u b l e im )
{
t h i s >r e = r e ;
t h i s >im = im ;
}
20
21
22
23
24
R e z u l t a t . im = t h i s >im + T2 . im ;
return Rezultat ;
25
26
27
28
Complex o p e r a t o r +( c o n s t d o u b l e &T2 )
{
Complex R e z u l t a t ;
R e z u l t a t . r e = t h i s >r e + T2 ;
R e z u l t a t . im = t h i s >im ;
return Rezultat ;
}
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
Complex o p e r a t o r ( c o n s t d o u b l e &T2 )
{
Complex R e z u l t a t ;
R e z u l t a t . r e = t h i s >r e T2 ;
R e z u l t a t . im = t h i s >im ;
return Rezultat ;
}
45
46
47
48
49
50
51
52
Complex o p e r a t o r ~ ( )
// o p e r a t o r u l ~ ( inseamna b i t w i s e NOT . . s i
n o i o s a i l f o l o s i m s a returnam c o n j u g a t u l numarului complex )
{
Complex R e z u l t a t ;
R e z u l t a t . r e = t h i s >r e ;
R e z u l t a t . im = t h i s >im ;
return Rezultat ;
}
53
54
55
56
57
58
59
60
void a f i s ( )
{
c o u t << t h i s >r e << "+" << t h i s >im << " i " << e n d l ;
}
61
62
63
64
65
};
66
67
68
69
70
71
i n t main ( )
{
Complex A( 5 , 1 ) ;
Complex B( 2 , 3 ) ;
Complex C ;
72
73
74
A. a f i s ( ) ; //5+1 i
B . a f i s ( ) ; //2+3 i
75
76
77
C = A + B;
C . a f i s ( ) ; //7+4 i
78
79
80
C = C + 3;
C . a f i s ( ) ; //10+4 i
81
C = C B;
C . a f i s ( ) ; //8+1 i
82
83
84
C = B 2;
C . a f i s ( ) ; //0+3 i
85
86
87
A = ~A;
A. a f i s ( ) ; //51 i
88
89
90
C = ~B ;
C . a f i s ( ) ; //23 i
91
92
93
2.2
Operatori de comparaie
#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
9
10
11
12
13
c l a s s Complex
{
double re ;
d o u b l e im ;
public :
Complex ( )
{
t h i s >r e = 0 ;
t h i s >im = 0 ;
}
14
15
16
17
18
19
Complex ( d o u b l e re , d o u b l e im )
{
t h i s >r e = r e ;
t h i s >im = im ;
}
20
Complex o p e r a t o r ~ ( )
{
Complex R e z u l t a t ;
R e z u l t a t . r e = t h i s >r e ;
R e z u l t a t . im = t h i s >im ;
return Rezultat ;
}
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
void a f i s ( )
{
c o u t << t h i s >r e << "+" << t h i s >im << " i " << e n d l ;
}
42
43
44
45
46
};
47
48
49
50
51
52
i n t main ( )
{
Complex A( 5 , 1 ) ;
Complex B( 2 , 3 ) ;
Complex C( 5 , 1 ) ;
53
A. a f i s ( ) ; //5+1 i
B . a f i s ( ) ; //2+3 i
C . a f i s ( ) ; //5+1 i
54
55
56
57
58
59
60
61
cout
cout
cout
cout
<<
<<
<<
<<
(A
(A
(A
(A
==
!=
==
!=
A)
A)
B)
B)
<<
<<
<<
<<
endl ;
endl ;
endl ;
endl ;
// 1
// 0
// 0
// 1
cout
cout
cout
cout
<<
<<
<<
<<
(A == ~B) << e n d l ;
// 0
(A == C) << e n d l ;
// 1
(~A == ~C) << e n d l ;
// 1
(~A != ~C) << e n d l ;
// 0
62
63
64
65
66
67
2.3
Operatorul de cast
#i n c l u d e <i o s t r e a m >
#i n c l u d e <math . h>
u s i n g namespace s t d ;
4
5
6
7
8
9
10
11
12
13
14
c l a s s Complex
{
double re ;
d o u b l e im ;
public :
Complex ( )
{
t h i s >r e = 0 ;
t h i s >im = 0 ;
}
15
Complex ( d o u b l e re , d o u b l e im )
{
t h i s >r e = r e ;
t h i s >im = im ;
}
16
17
18
19
20
21
22
23
24
25
26
void a f i s ( )
{
c o u t << t h i s >r e << "+" << t h i s >im << " i " << e n d l ;
}
27
28
29
30
31
32
};
33
34
35
36
37
38
i n t main ( )
{
Complex A( 5 , 2 ) ;
39
40
41
double d ;
d = ( d o u b l e )A;
42
43
A. a f i s ( ) ;
//5+2 i
10
44
45
// 5 . 3 8 . .
2.4
Operatorul subscript
Operatorul subscript, sau operatorul index este operatorul folosit de ctre iruri
(array-uri). Cum numrul nostru complex nu are efectiv iruri de numere, vom
folosi acest operator pentru a returna fie numrul real, fie pe cel imaginar, ca
n exemplul de mai jos:
1
2
3
#i n c l u d e <i o s t r e a m >
#i n c l u d e <math . h>
u s i n g namespace s t d ;
4
5
6
7
8
9
10
11
12
13
14
c l a s s Complex
{
double re ;
d o u b l e im ;
public :
Complex ( )
{
t h i s >r e = 0 ;
t h i s >im = 0 ;
}
15
16
17
18
19
20
Complex ( d o u b l e re , d o u b l e im )
{
t h i s >r e = r e ;
t h i s >im = im ;
}
21
22
23
24
d o u b l e& o p e r a t o r [ ] ( i n t i n d e x )
{
double i m p l i c i t = 0 ;
// o p e r a t o r u l s u b s c r i p t
25
switch ( index )
{
case 0:
r e t u r n t h i s >r e ;
break ;
case 1:
r e t u r n t h i s >im ;
break ;
default :
return i m p l i c i t ;
break ;
}
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
void a f i s ( )
{
c o u t << t h i s >r e << "+" << t h i s >im << " i " << e n d l ;
11
43
44
45
};
46
47
48
49
50
51
i n t main ( )
{
Complex A( 5 , 2 ) ;
52
A. a f i s ( ) ; //5+2 i
c o u t << A [ 0 ] << e n d l ; // 5
c o u t << A [ 1 ] << e n d l ; // 2
53
54
55
56
A[ 0 ] = 10;
A[ 1 ] = 3;
A. a f i s ( ) ; //10+3 i
57
58
59
60
2.5
Ne abatem puin din studiul operatorilor pentru a reaminti cteva lucruri despre
librria iostream - nelipsit din programele pe care le studiem. Aceast librrie
conine, pe lng numeroase clase i funcii de sistem i dou clase speciale:
istream i ostream. Astea modeleaz streamurile de intrare i de ieire. Fr
s intrm prea mult n detalii, cin i cout sunt dou OBIECTE, de tip
istream respectiv ostream. Practic sunt dou obiecte declarate deja n librria
iostream, obiecte ce tiu s fac legtura, n cazul nostru, cin ntre program i
tastatur, i cout ntre program i ecranul consolei.
1
#i n c l u d e <i o s t r e a m >
2
3
...
4
5
6
7
int variabila ;
c i n >> v a r i a b i l a ;
c o u t << v a r i a b i l a ;
2.6
Funcii friend
Cnd am vorbit prima data despre tipul de acces al variabilelor din clase i structuri, am zis c variabilele private i protected nu pot fi accesate din exteriorul
clasei, ci doar de funcii membre ale clasei. Acest lucru este total adevrat, cu
o excepie: clasele i funciile friend. O funcie friend este o funcie total
extern clasei dar care are acces i la membrii private i protected ai clasei.
Pentru ca o funcie f() s aib acces la membrii privai ai unei clase, acest
funcie trebuie s fie listat ca funcie friend. Un exemplu de funcie friend se
gsete n codul urmtor:
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
9
10
11
12
13
c l a s s Complex
{
double re ;
d o u b l e im ;
public :
Complex ( )
{
t h i s >r e = 0 ;
t h i s >im = 0 ;
}
14
Complex ( d o u b l e re , d o u b l e im )
{
t h i s >r e = r e ;
t h i s >im = im ;
}
15
16
17
18
19
20
f r i e n d v o i d f 1 ( Complex ) ;
21
22
};
23
24
25
26
27
28
v o i d f 1 ( Complex X)
{
c o u t << "Re = " << X. r e << e n d l ;
c o u t << "Im = " << X. im << e n d l ;
}
29
30
31
32
33
34
35
36
v o i d f 2 ( Complex X)
{
// a c e a s t a f u n c t i e i n c e a r c a s a a c c e s e z e r e s i im
// dar n e f i i n d f u n c t i e f r i e n d , nu a r e v o i e
c o u t << "Re = " << X. r e << e n d l ;
c o u t << "Im = " << X. im << e n d l ;
}
37
38
i n t main ( )
13
39
{
Complex A( 5 , 2 ) ;
40
41
f 1 (A) ;
f 2 (A) ;
42
43
44
// f u n c t i o n e a z a
// nu f u n c t i o n e a z a
n exemplul de mai sus funcia f1(Complex) este listat ca fiind prieten clasei
Complex, drept urmare are voie s acceseze membrii privai ai clasei, pe cnd
funcia f2(Complex) nu. Exemplul de mai sus nu este funcional la compilare
din cauz c funcia f2 ncearc s acceseze ceva ce nu are voie. Pentru a-l
face funcional, trebuie fie s tergem din funcia f2 liniile de cod care acceseaz
membri privai (liniile 34 i 35), fie s listm funcia f2 ca fiind funcie friend
clasei Complex.
Not. Adugnd o funcie la lista de funcii friend ale unei clase, nu este necesar ca funcia respectiv s i existe. Declarnd funcia ca fiind friend nseman
c orice funcie cu acel prototip va fi n mod implicit considerat friend.
Not. O funcie poate fi friend unui numr nelimitat de clase, i o clas poate
avea un numr nelimitat de funcii friend.
Pentru a lista o funcie ca fiind prieten a unei clase, tot ce trebuie s facem
este s scriem, n interiorul clasei, antetul funciei precedat de cuvntul friend
(vezi linia 21 din exemplul de mai sus).
2.7
Operatorii i
#i n c l u d e <i o s t r e a m >
2
3
4
5
6
c l a s s Complex
{
...
};
7
8
...
9
10
11
12
Complex A;
c i n >> A;
c o u t << A << e n d l ;
Pentru aceasta, aveam nevoie de informaii despre librria iostream, despre istream, ostream, cin, cout i despre funcii friend. Practic, pentru a putea realiza
ce dorim la liniile 11 i 12 din codul de mai sus, trebuie s suprancrcm operatorul al clasei istream i operatorul al clasei ostream. Aceti doi operatori
trebuiesc implementai n afara clasei Complex, deoarece dac ar fi implementai n interiorul acesteia, termenul stng al operatorilor sau ar fi this,
lucru care nu coincide cu ce dorim: membrul stng este de tip istream/ostream,
nu Complex.
14
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
9
10
11
12
13
c l a s s Complex
{
double re ;
d o u b l e im ;
public :
Complex ( )
{
t h i s >r e = 0 ;
t h i s >im = 0 ;
}
14
Complex ( d o u b l e re , d o u b l e im )
{
t h i s >r e = r e ;
t h i s >im = im ;
}
15
16
17
18
19
20
21
22
23
};
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
i n t main ( )
{
Complex A( 5 , 2 ) ;
41
c o u t << A << e n d l ;
42
43
c i n >> A;
c o u t << A << e n d l ;
44
45
46
15
2.8
c l a s s Complex
{
double re ;
d o u b l e im ;
public :
Complex ( )
{
t h i s >r e = 0 ;
t h i s >im = 0 ;
}
11
12
13
14
15
16
Complex ( d o u b l e re , d o u b l e im )
{
t h i s >r e = r e ;
t h i s >im = im ;
}
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
Complex o p e r a t o r +( c o n s t d o u b l e &T2 )
{
Complex R e z u l t a t ;
R e z u l t a t . r e = t h i s >r e + T2 ;
R e z u l t a t . im = t h i s >im ;
return Rezultat ;
}
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
Complex o p e r a t o r ( c o n s t d o u b l e &T2 )
{
Complex R e z u l t a t ;
R e z u l t a t . r e = t h i s >r e T2 ;
R e z u l t a t . im = t h i s >im ;
return Rezultat ;
}
49
50
51
52
53
Complex o p e r a t o r ~ ( )
{
Complex R e z u l t a t ;
R e z u l t a t . r e = t h i s >r e ;
16
R e z u l t a t . im = t h i s >im ;
return Rezultat ;
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
d o u b l e& o p e r a t o r [ ] ( i n t i n d e x )
{
double i m p l i c i t = 0 ;
76
77
78
// o p e r a t o r u l s u b s c r i p t
79
switch ( index )
{
case 0:
r e t u r n t h i s >r e ;
break ;
case 1:
r e t u r n t h i s >im ;
break ;
default :
return i m p l i c i t ;
break ;
}
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
};
97
98
99
100
101
102
103
104
105
106
107
108
109
17
Probleme
1. Pentru exemplul cu doi operatori+ din capitolul 2.1 exemplificai ordinea
operaiilor pentru linia de cod: C = A + B + C + 10;.
2. Tot pornind de la exemplul din capitolul 2.1 testai urmtoarea linie de
cod n main(): C = 2 + A;. Dac nu funcioneaz, cum o putem face s
funcioneze ?
3. Folosindu-v de funcia de calcul al modulului numrului complex, implementat la operatorul de cast, implementai operatorii de comparaie
> < >= <= care compar dou numere complexe n funcie de modulul
acestora.
4. Implementai clasa Lista care s modeleze o list dinamic de date, similar listei de la SDA. Avei grij c lista efectiv de date va fi alocat
dinamic, i din acest motiv avei nevoie de constructor de copiere, operator de copiere i destructor. Clasa Lista trebuie s conin operatorul
subscript prin care se poate accesa orice membru al listei la fel cum se
acceseaz un element al unui vector, trebuie s poat fi afiat folosind
cout, precum i urmtoarele funcii: adugare element la nceputul listei,
adugare element n interiorul listei dup un alt element, adugarea unui
element la sfritul listei i tergerea unui element.
5. Folosind clasa Lista implementat la exerciiul anterior, adugai un membru private numit sortat. Dac acest element este 1, lista trebuie meninut ordonat cresctor (inclusiv la adugare i stergere).
18