Documente Academic
Documente Profesional
Documente Cultură
Supraincarcareaoperatorilor
Supraincarcareaoperatorilor
Supraincarcareaoperatorilor
CAP. 3
Supraîncărcarea(engl.,overloading)operatorilorpermiteatribuireadenoisemnificaţiioperatoriloruzuali(ope
ratorilorîntâlniţipentrutipurilededatepredefinite).
Supraincarcareaoperatorilor
CAP. 3
Clasareprezintăuntipdedate(omulţimedevaloripentrucares-
aadoptatunanumitmoddereprezentareşiomulţimedeoperaţiicarepotfiaplicateacestora).Astfel,operatorul
+foloseştelaadunareaadouădatedetipint,floatsaudouble,însăaceluiaşioperatorisepoateatribuisemnificaţi
ade“alipire”adouăobiectedetipşir,saudeadunareadouăobiectedetipulcomplex,vectorsaumatrice.
Supraincarcareaoperatorilor
CAP. 3
Observaţie:
Operatoriisuntdejasupraîncărcaţipentruaputeaopera
asupramaimultortipuridebază(deexemplu,operatorul+admiteoperanzidetipint,darşifloatsaudouble),saup
otaveasemnificaţiidiferite(deexemplu,operatorul*poatefifolositpentruînmulţireaadoioperanzinumericisa
ucaoperatordedeferenţiere,operatorul>>poateaveasemnificatiadeoperatorextractorsauoperatordedepla
sareladreapta,laniveldebit).
Supraincarcareaoperatorilor
CAP. 3
Prinsupraîncărcareaoperatorilor,operaţiilecarepotfiexecutateasuprainstantelor(obiectelor)uneiclasepotfi
folositecasiincazultipurilordedatepredefinite.
Supraincarcareaoperatorilor
CAP. 3
Deci,limbajulC++permitesupraincarcareaoperatorului<op>prindefinireauneifunctiinumite
operator<simbol_op>
expresia a+b (a, b sunt obiecte din clasa punct) reprezintă “suma” a două puncte şi este un punct ale
cărui coordonate sunt date de suma coordonatelor punctelor a şi b. Astfel,
supraincarcareaoperatorului+ constain definireauneifunctiicu numeleoperator +:
Supraincarcareaoperatorilor
10
CAP. 3
Funcţia trebuie să poată accesa datele membre private ale clasei, deci supraîncărcarea operatorilor se
poate realiza în două moduri:
Supraincarcareaoperatorilor
11
CAP. 3
Supraincarcareaoperatorilor
12
CAP. 3
Exemplu:
Expresia C=A+B este interpretată ca C = A.operator + (B). Expresia C=A+B+C poate fi interpretată, în
funcţie de compilator, astfel: Unele compilatoare crează un obiect temporar T: T = A.operator + (B) C =
T.operator+ (C) Alte compilatoare interpretează expresia ca: C=(A.operator+(B)).operator+(C).
Supraincarcareaoperatorilor
13
CAP. 3
Consideramclasapunctdefinităanterior.funcţiileprieteneauacceslamembriiprivaţiaiunei
clase,însăNUprimesccaargumentimplicitpointerulcătreobiectulcurent(this)săsupraîncărcămacelaşioper
atorbinardeadunare,+,printr-ofuncţieprietenăaclaseipunct:
Supraincarcareaoperatorilor
14
CAP. 3
Expresia C=A+B este interpretată de compilator ca C=operator + (A, B). Expresia C=A+B+C este evaluată
ţiinându-se cont de regulile de prioritate şi de asociativitate a operatorului: (A+B)+C, ceea ce conduce la
un apel de forma: operator+(operator+(A, B), C).
Supraincarcareaoperatorilor
15
CAP. 3
Observaţie:
Supraincarcareaoperatorilor
16
CAP. 3
Observaţie:
La transmiterea parametrilor prin referinţă, funcţia prietenă operator +are prototipul: punctoperator +
(punct&, punct&); Pentru a proteja argumentele transmise prin referinţă la modificările
care ar putea fi realizate asupra acestora în corpul funcţiei, se poate folosi modificatorul de acces const:
Supraincarcareaoperatorilor
17
Supraincarcareaoperatorilor
18
CAP. 3
Supraîncărcarea operatorilor se poate realiza, deci, prin funcţii membre sau funcţii prietene. Dacă
supraîncărcăm acelaşi operator printr-o metodă şi printr-o funcţie prietenă, funcţia prietenă va avea,
întotdeauna, un parametru în plus faţă de metodă (deoarece funcţiei prietene nu i se transmite ca
parametru implicit pointerul this).
Supraincarcareaoperatorilor
19
CAP. 3
Totuşi, supraîncărcarea operatorilor este supusă următoarelor restricţii:Se pot supraîncărca doar
operatorii existenţi; nu se pot crea noi operatori. Nu se poate modifica aritatea (numărul de operanzi)
operatorilor limbajului (operatorii unari nu pot fi supraincărcaţi ca operatori binari, şi invers). Nu se
poate modifica precedenţa şi asociativitatea operatorilor.
Supraincarcareaoperatorilor
20
CAP. 3
Supraincarcareaoperatorilor
21
CAP. 3
Observaţii:
Supraincarcareaoperatorilor
22
CAP. 3
Observaţii:
Funcţia operator trebuie să aibă cel puţin un argument (implicit sau explicit) de tipul clasei pentru care
s-a supraîncărcat operatorul. Astfel:oLa supraîncărcarea unui operator unar printr-o funcţie membră a
clasei, aceasta are un argument implicit de tipul clasei (obiectul care îl apelează) şi nici un argument
explicit. La supraîncărcarea operatorului unar printr-o funcţie prietenă, aceasta are un argument
explicitde tipul clasei.oLa supraîncărcarea unui operator binar printr-o funcţie membră a clasei, aceasta
are un argument implicit de tipul clasei (obiectul care îl apelează) şi un argument explicit. La
supraîncărcarea operatorului binar printr-o funcţie prietenă, aceasta are două argumente explicitede
tipul clasei.
Supraincarcareaoperatorilor
23
CAP. 3
Se poate atribui unui operator orice semnificaţie, însă este de dorit ca noua semnificaţie să fie cât mai
apropiată de semnificaţia naturală.
Deexemplu,pentruadunareaadouăobiectesepoatesupraîncărcaoperatorul*,darestemainaturalăfolosirea
operatorului+cusemnificaţiadeadunare.
Supraincarcareaoperatorilor
24
CAP. 3
În cazul supraîncărcării operatorilor, nu se poate conta pe comutativitatea acestora. De exemplu, dacă
se supraîncarcă operatorul + pentru clasa complex printr-o funcţie prietenă a clasei complex, aceasta va
avea prototipul: complex operator + (complex, double)
Operatorulpoatefifolositînexpresiicumarfi:a+7.8(aesteobiectalclaseicomplex),darnuînexpresiica:7.8+a.
Supraincarcareaoperatorilor
25
CAP. 3
Dacă un operator trebuie să primească ca prim parametru un tip predefinit, acesta nu poate fi
supraîncărcat printr-o funcţie membră. Operatorii care prezintă şi alte particularităţi, vor fi trataţi
separatÎn principiu, metodele care supraîncarcă un operator nu sunt statice. Excepţia o constituie
operatorii newşi delete. Diferenţa între forma prefixată şi postfixată, la supraîncărcarea operatorilor
predefiniţi ++ şi --, se poate face doar de anumite compilatoare (de exemplu, compilatorul de BorlandC,
versiune>3.0, se poate face diferenţa).
Supraincarcareaoperatorilor
26
Supraincarcareaoperatorilor
27
CAP. 3
Operatorii unari pot fi supraîncărcaţi printr-o funcţie membrănestatică (fără parametri expliciţi) sau
printr-o funcţie prietenă cu un parametru explicit de tipul clasă. Ca exemplu, să supraîncărcăm
operatorul unar ++pentru clasa punct, pentru a putea fi folosit atât în formă prefixată, cât şi postfixată
(doar pentru compilatoarele care permit acest lucru!!).
Supraincarcareaoperatorilor
28
CAP. 3
Vom folosi clasa punct implementată anterior, cu modificarea ca datele membre sunt de tipul int.class
punct{int x, y;
public: // . . .punct operator ++ (int ); //forma postfixată punct & operator++(); //forma
prefixată};punctpunct::operator ++ (int) {punctp=*this; x++; y++;return p;} punct& punct::operator++()
{x++; y++; return *this;}intmain() { punctA(11, 10); punctC=A++;A.afişare( ); C.afişare( ); punctC=+
+A;A.afişare( ); C.afişare( ); }
Supraincarcareaoperatorilor
29
30
CAP. 3
O clasă poate avea membrii statici: date membru statice (figurează într-un singur exemplar pentru
toate instanţele clasei) metode statice (nu li se transmite pointerul this şi pot modifica doar date
membru statice). O clasă poate avea metode constante. O metodă este declarată constantă prin
utilizarea modificatorului constîn antetul ei, după lista parametrilor formali. Metodele constante nu
modifică obiectul pentru care sunt apelate.
Supraincarcareaoperatorilor
31
CAP. 3
Ca oricăror variabile de tip predefinit, şi obiectelorde tip definit de utilizator li se poate aplica
modificatorul const. Pentru un obiect constant este permis doar apelul metodelor constante, a
constructorilor şi a destructorilor.
Supraincarcareaoperatorilor
32
Supraincarcareaoperatorilor
33
CAP. 3
Supraincarcareaoperatorilor
34
CAP. 3
complexz1,z2;cin>>z1>>z2;//extragevalorileluiz1şiz2cout<<"z1="<<z1<<'\n';//insereazăşirconstant,apoiv
aloarealuiz1cout<<"z2="<<z2<<'\n';//insereazăşirconstant,apoivaloarealuiz2
Supraincarcareaoperatorilor
35
CAP. 3
Deoareceîntotdeaunaoperandulstângestedetipistream(cinesteobiectpredefinit,detipistream)sauostream
(coutesteobiectpredefinit,detipostream),şinudetipulintrodusprinclasă,operatorii<<şi>>potfisupraîncărca
ţinumaiprinfuncţiiprietene.
Supraincarcareaoperatorilor
36
CAP. 3
Prototipurileoperatorilorsunt:
(pentrutipuldedatecomplex)
friendostream&operator<<(ostream&,constcomplex&);
//operatorafişarecomplex
friendistream&operator>>(istream&,complex&);
//operatorcitirecomplex
Supraincarcareaoperatorilor
37
CAP. 3
Definiţiilefuncţiiloroperator:ostream&operator<<(ostream&ecran,constcomplex&z)
{ecran<<"("<<z.re;if(z.im>=0)ecran<<'+';ecran<<z.im<<"*i)";returnecran;}istream&operator>>(istream&t
astatura,complex&z){tastatura>>z.re>>z.im;returntastatura;}
Supraincarcareaoperatorilor
38
CAP. 3
3.5. SUPRAINCARCAREA OPERATORILOR INSERTORSI EXTRACTOR
Prototipurilefuncţiiloroperator<<şi>>pentruuntipabstracttip,sunt:
Supraincarcareaoperatorilor
39
CAP. 3
Exerciţiu:
Se defineşte tipul de date DateTime, cu data membră _bintime, de tipul time_t(definit în header-ul
time.h). Pentru acest tip de date s-au definit 2 constructori, metoda afiş, şi s-au supraîncărcat
operatorii: +(prin două funcţii prietene care pot realiza operaţii de forma d+n, respectiv n+d –n de tip
întreg, dde tip DateTime) care adună la data curentă un număr de zile; +=(prin metodă); <<(operatorul
insertor, prin funcţie prietenă).
Supraincarcareaoperatorilor
40
CAP. 3
Supraincarcareaoperatorilor
41
CAP. 3
Supraincarcareaoperatorilor
42
CAP. 3
3.5. SUPRAINCARCAREA OPERATORILOR INSERTOR SI EXTRACTOR//-----------------------------------
Programulde test -----------------------------#include "datetime.h" intmain(void) { DateTime d1;cout <<
"Data curenta si ora = " << d1 << ’\n’; d1 += 45;cout << "Peste 45 de zile, va fi " << d1 <<’\n’; cout<<
"Pesteinca5 zile, vafi "; cout<< d1+5 << endl; }
Supraincarcareaoperatorilor
43
Supraincarcareaoperatorilor
44
CAP. 3
Încazulîncareoperatoruldeatribuirenuestesupraîncărcatexplicit,compilatorulgenereazăunulimplicit(caîne
xemplulclaseipunctsausegment).Înabsenţauneisupraîncărcăriexplicite,operatorulcopievaloriledatelorme
mbrealeoperanduluidreptîndatelemembrealeoperanduluistâng.
Supraincarcareaoperatorilor
45
CAP. 3
Exemplu:
puncta(8,9),b;b=a;/*operatoratribuireimplicit:zonadememorieocupatadeobiectulasecopie,bitcubit,înzon
adememorieocupatădeb:b.x=a.xşib.y=a.y*/Operatoruldeatribuireimplicitestenesatisfăcătorînsituaţiileînc
areobiecteleclaseiaucadatemembrepointeri,sauînsituaţiileîncarememoriaestealocatăînmoddinamic.
Supraincarcareaoperatorilor
46
CAP. 3
Supraincarcareaoperatorilor
47
CAP. 3
O altă modalitate, mai eficientă, de a supraîncărca operatorul de atribuire prin metodă a clasei complex,
este aceea prin care funcţia primeşte ca parametru referinţăcătre operandul drept (se lucrează, astfel,
chiar cu obiectul b, deoarece z şi b sunt variabile referinţă; în plus, modificatorul const interzice
modificarea operandului transmis ca parametru referinţă; în plus, nu se mai crează obiectul local z, se ia
ca referinţă obiectul existent) şi returnează o referinţă (adresa obiectului a), aşa cum prezintă figura.
Supraincarcareaoperatorilor
48
CAP. 3
Supraincarcareaoperatorilor
49
CAP. 3
Deasemenea, operatorul binar de atribuire poate fi supraîncărcat prinfuncţie prietenă (în acest caz, nu
primeşte parametrul implicit this, deci are doi operanzi). Paramertrii z1, z2 sunt transmişi prin referinţă,
deci se lucrează chiar cu obiectele a, b. Funcţia returnează adresa obiectului a. Modificatorul const
interzice modificarea operandului drept.
Supraincarcareaoperatorilor
50
CAP. 3
Supraincarcareaoperatorilor
51
CAP. 3
Deoareceîntotdeaunaoperandulstângaloperatoruluideatribuireestedetipulclaseipentrucaresesupraîncarc
ă,estepreferabilcasupraîncărcareasăserealizezeprin
metodăaclasei.
Reamintimcăasociativitateaoperatoruluiestedeladreaptalastânga.Operatorulpoateapareînexpresiidefor
ma:a=b=c=d;
Supraincarcareaoperatorilor
52
CAP. 3
Supraincarcareaoperatorilor
53
CAP. 3
Supraincarcareaoperatorilor
54
CAP. 3
55
CAP. 3
Supraincarcareaoperatorilor
56
CAP. 3
Supraincarcareaoperatorilor
57
CAP. 3
Supraincarcareaoperatorilor
58
CAP. 3
59
CAP. 3
Supraincarcareaoperatorilor
60
CAP. 3
Supraincarcareaoperatorilor
61
CAP. 3
Supraincarcareaoperatorilor
62
CAP. 3
Supraincarcareaoperatorilor
63
CAP. 3
Supraincarcareaoperatorilor
64
CAP. 3
Supraincarcareaoperatorilor
65
CAP. 3
Supraincarcareaoperatorilor
66
CAP. 3
Supraincarcareaoperatorilor
67
CAP. 3
3.6. SUPRAINCARCAREA OPERATORULUI DE ATRIBUIRE =Pentru a evita lucrul cu fişiere care au sute de
linii de cod, se folosesc două abordări: a) Se crează fişierul sursă numit fractie.h(header al utilizatorului)
care conţine declararea clasei fracţie. Se crează fişierul fractie.cppîn care se implementează metodele
clasei fracţie. În acest fişier se include header-ul "fractie.h". Se crează un al treilea fişier care testează
tipul de date fracţie, în care se include fişierului "fractie.cpp". Se compilează, se linkeditează şi se
lansează în execuţie fişierul executabil obţinut.
Supraincarcareaoperatorilor
68
CAP. 3
Supraincarcareaoperatorilor
69
CAP. 3
3.6. SUPRAINCARCAREA OPERATORULUI DE ATRIBUIRE =Pentru a evita includerea aceluiaşi fişier header
de mai multe ori, se folosesc directivele de compilare condiţionată.
Exemplu:
70
CAP. 3
To be continued…
Supraincarcareaoperatorilor
Supraincarcareaoperatorilor
71
Programareacalculatoarelorşilimbajede programareII