Sunteți pe pagina 1din 18

CAPITOLUL 3

Supraincarcareaoperatorilor

Supraincarcareaoperatorilor

1. Moduride supraincarcarea operatorilor2. Restrictiila supraincarcareaoperatorilor3.


Supraincarcareaoperatorilorunari4. Membriiconstantiaiclasei5.
Supraincarcareaoperatorilorinsertorsiextractor6. Supraincarcareaoperatoruluide atribuire=7.
Supraincarcareaoperatoruluide indexare[ ]8. Supraincarcareaoperatorilornewsidelete9.
Supraincarcareaoperatorului( )10.Supraincarcarea operatorului->11.ConversiiCAP. 3

Supraincarcareaoperatorilor

CAP. 3

3.1. Moduride supraincarcarea operatorilor

Supraîncărcarea(engl.,overloading)operatorilorpermiteatribuireadenoisemnificaţiioperatoriloruzuali(ope
ratorilorîntâlniţipentrutipurilededatepredefinite).

Supraincarcareaoperatorilor

CAP. 3

3.1. Moduride supraincarcarea operatorilor

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

3.1. Moduride supraincarcarea operatorilor

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

3.1. Moduride supraincarcarea operatorilor

Prinsupraîncărcareaoperatorilor,operaţiilecarepotfiexecutateasuprainstantelor(obiectelor)uneiclasepotfi
folositecasiincazultipurilordedatepredefinite.

Supraincarcareaoperatorilor

CAP. 3

3.1. Moduride supraincarcarea operatorilor

[<tip_val_ret>] operator <simbol_op> (<lista_declar_par>) { //……. corpulfunctiei}

Deci,limbajulC++permitesupraincarcareaoperatorului<op>prindefinireauneifunctiinumite

operator<simbol_op>

Exemplu: Pentru clasa punct, putem atribui operatorului + semnificaţia:

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

3.1. Moduride supraincarcarea operatorilor

Funcţia trebuie să poată accesa datele membre private ale clasei, deci supraîncărcarea operatorilor se
poate realiza în două moduri:

printr-o funcţie membră a clasei; printr-o funcţie prietenă a clasei.

Supraincarcareaoperatorilor

11

CAP. 3

3.1. Moduride supraincarcarea operatorilor


În situaţia în care, pentru clasa punct, supraîncărcareaoperatorului binar de adunare, +, se realizează
printr-o funcţie membră, aceasta primeşte ca parametru implicit adresa obiectului curent (pentru care
este apelată). Deci primul operand al operatorului este transmis implicit, iar al doilea operandeste
parametrul transmis explicit.

3.1.1 SUPRAÎNCĂRCAREA OPERATORILOR PRIN FUNCŢII MEMBRE

Supraincarcareaoperatorilor

12

CAP. 3

3.1. Moduride supraincarcarea operatorilor3.1.1 SUPRAÎNCĂRCAREA OPERATORILOR PRIN FUNCŢII


MEMBRE

Exemplu:

class punct{ double x, y; public: // . . . . . . vezicapitolulanterior punctoperator + (punct); };


//Metodeleclaseipunct…………………… punctpunct::operator + (puncta) {punctp; p.x=x + a.x;
//echivalentcup.x=this->x+a.x; p.y=y + a.y; //echivalentcu p.y=this->y+a.y; return p; }intmain()
{ punctA(1.1, 2.2); A.afişare(); punctB(-5.5, -6.6); B.afişare(); punctC; C=A+B; C.afişare(); C=A+B+C;
C.afişare(); }

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

3.1. Moduride supraincarcarea operatorilor3.1.1 SUPRAÎNCĂRCAREA OPERATORILOR PRIN FUNCŢII


PRIETENE

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

3.1. Moduride supraincarcarea operatorilor3.1.1 SUPRAÎNCĂRCAREA OPERATORILOR PRIN FUNCŢII


PRIETENEclass punct{ double x, y; public: // . . . . . . friend punctoperator + (punct,
punct); };//Metodeleclaseipunct……………………. punctoperator + (puncta, punctb) {punctp; p.x=a.x+ b.x;
p.y=a.y+ b.y; return p; }main() { punctA(1.1, 2.2); A.afişare(); punctB(-5.5, -6.6); B.afişare(); punctC;
punctC=A+B; C.afişare(); C=A+B+C; C.afişare(); }

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

3.1. Moduride supraincarcarea operatorilor3.1.1 SUPRAÎNCĂRCAREA OPERATORILOR PRIN FUNCŢII


PRIETENE

Observaţie:

În exemplul anterior, transmiterea parametrilor către funcţia prietenă de supraîncărcare a operatorului


+se realizează prin valoare. Parametrii pot fi transmişi şi prin referinţă, pentru a evita crearea (în
momentul apelului funcţiei) unor copii locale ale parametrilor efectivi în cei formali.

Supraincarcareaoperatorilor

16

CAP. 3

3.1. Moduride supraincarcarea operatorilor3.1.1 SUPRAÎNCĂRCAREA OPERATORILOR PRIN FUNCŢII


PRIETENE

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:

punctoperator + (constpunct&, constpunct&);

Supraincarcareaoperatorilor

17

1. Moduride supraincarcarea operatorilor2. Restrictiila supraincarcareaoperatorilor3.


Supraincarcareaoperatorilorunari4. Membriiconstantiaiclasei5.
Supraincarcareaoperatorilorinsertorsiextractor6. Supraincarcareaoperatoruluide atribuire= 7.
Supraincarcareaoperatoruluide indexare[ ] 8. Supraincarcareaoperatorilornew sidelete9.
Supraincarcareaoperatorului( ) 10.Supraincarcarea operatorului-> 11.ConversiiCAP. 3

Supraincarcareaoperatorilor

18
CAP. 3

3.2. RESTRICŢII LA SUPRAÎNCĂRCAREA OPERATORILOR

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

3.2. RESTRICŢII LA SUPRAÎNCĂRCAREA OPERATORILOR

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

3.2. RESTRICŢII LA SUPRAÎNCĂRCAREA OPERATORILOR

Totuşi, supraîncărcarea operatorilor este supusă următoarelor restricţii:(cont)operatorii supraîncărcaţi


păstrează aritatea şi precedenţa operatorilor predefiniţi, darnumoştenesc şi comutativitateaacestora.
Nu pot fi supraîncărcaţi operatorii .(operatorul selector al unui membru), .*(operatorul de
deferenţiere, selecţie indirectă a unui membru), ::(de rezoluţie, de apartenenţă, scop) şi ?:(operatorul
condiţional).

Supraincarcareaoperatorilor

21

CAP. 3

3.2. RESTRICŢII LA SUPRAÎNCĂRCAREA OPERATORILOR

Observaţii:

Revedetitabelulcu operatoriiexistenţi, precedenţaşiasociativitateaacestora. Dacă operatorul = (de


atribuire) nu este supraîncărcat, el are o semnificaţie implicită. Operatorii , new delete [ ] -> şi de
conversie explicită impun restricţii suplimentarecare vor fi discutate ulterior.

Supraincarcareaoperatorilor

22
CAP. 3

3.2. RESTRICŢII LA SUPRAÎNCĂRCAREA OPERATORILOR

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

3.2. RESTRICŢII LA SUPRAÎNCĂRCAREA OPERATORILOR

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

3.2. RESTRICŢII LA SUPRAÎNCĂRCAREA OPERATORILOR

Î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

3.2. RESTRICŢII LA SUPRAÎNCĂRCAREA OPERATORILOR

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

1. Moduride supraincarcarea operatorilor2. Restrictiila supraincarcareaoperatorilor3.


Supraincarcareaoperatorilorunari4. Membriiconstantiaiclasei5.
Supraincarcareaoperatorilorinsertorsiextractor6. Supraincarcareaoperatoruluide atribuire= 7.
Supraincarcareaoperatoruluide indexare[ ]8. Supraincarcareaoperatorilornewsidelete9.
Supraincarcareaoperatorului( ) 10.Supraincarcarea operatorului->11.ConversiiCAP. 3

Supraincarcareaoperatorilor

27

CAP. 3

3.3. SUPRAÎNCĂRCAREA OPERATORILOR UNARI

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

3.3. SUPRAÎNCĂRCAREA OPERATORILOR UNARI

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

1. Moduride supraincarcarea operatorilor2. Restrictiila supraincarcareaoperatorilor3.


Supraincarcareaoperatorilorunari4. Membriiconstantiaiclasei5.
Supraincarcareaoperatorilorinsertorsiextractor6. Supraincarcareaoperatoruluide atribuire= 7.
Supraincarcareaoperatoruluide indexare[ ] 8. Supraincarcareaoperatorilornew sidelete9.
Supraincarcareaoperatorului( ) 10.Supraincarcarea operatorului-> 11.ConversiiCAP. 3
Supraincarcareaoperatorilor

30

CAP. 3

3.4. MEMBRII CONSTANTI AI UNEI CLASE

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

3.4. MEMBRII CONSTANTI AI UNEI CLASE

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

1. Moduride supraincarcarea operatorilor2. Restrictiila supraincarcareaoperatorilor3.


Supraincarcareaoperatorilorunari4. Membriiconstantiaiclasei5.
Supraincarcareaoperatorilorinsertorsiextractor6. Supraincarcareaoperatoruluide atribuire=7.
Supraincarcareaoperatoruluide indexare[ ]8. Supraincarcareaoperatorilornewsidelete9.
Supraincarcareaoperatorului( ) 10.Supraincarcarea operatorului->11.ConversiiCAP. 3

Supraincarcareaoperatorilor

33

CAP. 3

3.5. SUPRAINCARCAREA OPERATORILOR INSERTORSI EXTRACTOR

Operatorul<<se numeşte operatorinsertor, deoarece insereazădate în stream-ul (fluxul) de ieşire.


Operatorul>>se numeşte operatorextractor, deoarece extragedate din stream-ul (fluxul) de intrare.

Supraincarcareaoperatorilor

34

CAP. 3

3.5. SUPRAINCARCAREA OPERATORILOR INSERTORSI EXTRACTOR


Înexemplulurmător,aceştioperatorisuntsupraîncărcaţipentruclasacomplex,astfelîncâtsăpoatăfifolosiţicap
entruobiecteledetippredefinit.Exemplu:

complexz1,z2;cin>>z1>>z2;//extragevalorileluiz1şiz2cout<<"z1="<<z1<<'\n';//insereazăşirconstant,apoiv
aloarealuiz1cout<<"z2="<<z2<<'\n';//insereazăşirconstant,apoivaloarealuiz2

Supraincarcareaoperatorilor

35

CAP. 3

3.5. SUPRAINCARCAREA OPERATORILOR INSERTORSI EXTRACTOR

Deoareceîntotdeaunaoperandulstângestedetipistream(cinesteobiectpredefinit,detipistream)sauostream
(coutesteobiectpredefinit,detipostream),şinudetipulintrodusprinclasă,operatorii<<şi>>potfisupraîncărca
ţinumaiprinfuncţiiprietene.

Supraincarcareaoperatorilor

36

CAP. 3

3.5. SUPRAINCARCAREA OPERATORILOR INSERTORSI EXTRACTOR

Prototipurileoperatorilorsunt:

(pentrutipuldedatecomplex)

friendostream&operator<<(ostream&,constcomplex&);

//operatorafişarecomplex

friendistream&operator>>(istream&,complex&);

//operatorcitirecomplex

Supraincarcareaoperatorilor

37

CAP. 3

3.5. SUPRAINCARCAREA OPERATORILOR INSERTORSI EXTRACTOR

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:

friendostream&operator<<(ostream&,consttip&); friendistream&operator >> (istream&,tip&);

Supraincarcareaoperatorilor

39

CAP. 3

3.5. SUPRAINCARCAREA OPERATORILOR INSERTOR SI EXTRACTOR

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

3.5. SUPRAINCARCAREA OPERATORILOR INSERTOR SI EXTRACTOR//----------------------------------------------


datetime.h-----------------------------------------------#if !defined(__DATETIME_H) #define __DATETIME_H
#include <time.h> // funcţiiANSI standard "Time" #include <iostream.h> // pentrustream-uriI/O class
DateTime{ private: time_t_bintime; public: DateTime() { time(&_bintime); } DateTime(time_tt) :
_bintime(t) { } friend DateTime operator+(DateTime d, int n) { structtm *ltime= localtime(&d._bintime);
ltime->tm_mday+= n; time_tt = mktime(ltime); return DateTime(t); }

Supraincarcareaoperatorilor

41

CAP. 3

3.5. SUPRAINCARCAREA OPERATORILOR INSERTOR SI EXTRACTORfriend DateTime operator+(int n,


DateTime d) { return d+n; } DateTimeoperator+=(intn) {structtm *ltime= localtime(&_bintime); ltime-
>tm_mday+= n; _bintime= mktime(ltime); return *this; } void afis(ostream& os) { os <<
ctime(&_bintime);} friend ostream& operator<<(ostream& os, DateTime& d) {d.afis(os); return os; } };
#endif

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

1. Moduride supraincarcarea operatorilor2. Restrictiila supraincarcareaoperatorilor3.


Supraincarcareaoperatorilorunari4. Membriiconstantiaiclasei5.
Supraincarcareaoperatorilorinsertorsiextractor6. Supraincarcareaoperatoruluide atribuire=7.
Supraincarcareaoperatoruluide indexare[ ] 8. Supraincarcareaoperatorilornewsidelete9.
Supraincarcareaoperatorului( ) 10.Supraincarcarea operatorului->11.ConversiiCAP. 3

Supraincarcareaoperatorilor

44

CAP. 3

3.6. SUPRAINCARCAREA OPERATORULUI DE ATRIBUIRE =

Încazulîncareoperatoruldeatribuirenuestesupraîncărcatexplicit,compilatorulgenereazăunulimplicit(caîne
xemplulclaseipunctsausegment).Înabsenţauneisupraîncărcăriexplicite,operatorulcopievaloriledatelorme
mbrealeoperanduluidreptîndatelemembrealeoperanduluistâng.

Supraincarcareaoperatorilor

45

CAP. 3

3.6. SUPRAINCARCAREA OPERATORULUI DE ATRIBUIRE =

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

3.6. SUPRAINCARCAREA OPERATORULUI DE ATRIBUIRE =O supraîncărcare explicită a operatorului


pentru clasa complex (ambii operanzi de tip complex) poate fi făcută fie prin metodă, fie prin funcţie
prietenă. class complex { double re,im; public: complex operator = (complex ); }; complex
complex::operator = (complex z) { re=z.re; im=z.im; return *this; //this este pointer către obiectul
curent, a în main} intmain() {complex a, b; a = b; //a.operator=(b); (v. figura) }

Deoarece funcţiaoperator = returnează valoare de tip complex, se construieşte un obiect temporar


temp, a cărui valoare se atribuie lui a.

Supraincarcareaoperatorilor

47

CAP. 3

3.6. SUPRAINCARCAREA OPERATORULUI DE ATRIBUIRE =

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

3.6. SUPRAINCARCAREA OPERATORULUI DE ATRIBUIRE =

complex &complex::operator=(constcomplex &z) { re=z.re; im=z.im; return *this;} intmain() {complex a,


b;a = b; //a.operator=(b); (v. figura) }

Supraincarcareaoperatorilor

49

CAP. 3

3.6. SUPRAINCARCAREA OPERATORULUI DE ATRIBUIRE =

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

3.6. SUPRAINCARCAREA OPERATORULUI DE ATRIBUIRE =class complex { double re,im; public:


friendcomplex&operator=(complex&, constcomplex&); //funcţie prietenă constantă }; complex
&operator=(complex &z1,complex &z2) {z1.re=z2.re;z1.im=z2.im; return z1;} intmain() {complex a, b; a =
b; //a.operator=(b); (v. figura) }

Supraincarcareaoperatorilor

51

CAP. 3

3.6. SUPRAINCARCAREA OPERATORULUI DE ATRIBUIRE =

Deoareceîntotdeaunaoperandulstângaloperatoruluideatribuireestedetipulclaseipentrucaresesupraîncarc
ă,estepreferabilcasupraîncărcareasăserealizezeprin

metodăaclasei.

Reamintimcăasociativitateaoperatoruluiestedeladreaptalastânga.Operatorulpoateapareînexpresiidefor
ma:a=b=c=d;

Supraincarcareaoperatorilor

52

CAP. 3

3.6. SUPRAINCARCAREA OPERATORULUI DE ATRIBUIRE =//FISIERUL complex.h#define PI


3.14159265358979 #include <iostream.h> class complex { double re,im; public: complex(double
r=0,double i=0); //constructorcomplex(constcomplex&); //constructorcopiere~complex()
{cout<<"Destructor complex("<<re<<","<<im<<")\n";} //destructor double modul(); //metodacare
returneazamodululunuicomplex

Supraincarcareaoperatorilor

53

CAP. 3

3.6. SUPRAINCARCAREA OPERATORULUI DE ATRIBUIRE =double arg(); //metodacare


returneazaargumentulunuicomplex void ipi(); // metodacare incrementeazaparteaimag. void dpi();
//met. de decrem. a partii imag // operator + binarfriendcomplex operator+
(constcomplex&,constcomplex&); // complex + complex friendcomplex operator+
(constdouble,constcomplex &); // real + complex friendcomplex operator +(constint,constcomplex
&);//int+complexfriendcomplex operator +(constcomplex&,constdouble); // complex + double

Supraincarcareaoperatorilor

54

CAP. 3

3.6. SUPRAINCARCAREA OPERATORULUI DE ATRIBUIRE =complex operator -(constcomplex &) const;


//operator -binar: complex -complex //operator inmultirebinar: complex * complex friendcomplex
operator *(constcomplex &,constcomplex &); complex operator *(constcomplex ) const;
Supraincarcareaoperatorilor

55

CAP. 3

3.6. SUPRAINCARCAREA OPERATORULUI DE ATRIBUIRE =/*TEMA: friend complex operator /


(constcomplex &,constcomplex &); complex operator / (constcomplex &); */ complex & operator + ()
const; //operator + unar; metodă constantă complex operator -() const; //operator -unarcomplex
&operator=(constcomplex &); complex & operator += (constcomplex &z); complex operator +=
(constdouble); complex operator -= (constcomplex&); complex & operator /= (constcomplex &z);

Supraincarcareaoperatorilor

56

CAP. 3

3.6. SUPRAINCARCAREA OPERATORULUI DE ATRIBUIRE =/* TEMA complex operator *=


(constcomplex&); complex operator /= (constcomplex&);*/ complex & operator ++ (); //forma prefixată
complex operator ++ (int); //forma postfixată complex operator--(); //decrementarea părţii reale a
obiectului complex curent complex operator ! (); //calcul. rădăcinii pătrate a obiectului complex curent
intoperator == (complex &z); //compară doi complecşi şi returnează 1 în caz de egalitate friend
intoperator==(complex &, complex &); //return. 1 daca 2 complecsi egali intoperator != (complex &);
friend intoperator != (complex &, complex &); friend
ostream&operator<<(ostream&,constcomplex&); //operator afisarecomplex friend istream& operator
>> (istream&,complex&); //operator citirecomplex };

Supraincarcareaoperatorilor

57

CAP. 3

3.6. SUPRAINCARCAREA OPERATORULUI DE ATRIBUIRE =// FISIERUL complex.cpp #include "complex.h"


#include <stdlib.h> #include <math.h> inlinecomplex::complex(double r, double i)
{re=r;im=i;cout<<"Constructor implicit ptrcomplex("; cout<<re<<","<<im<<")\n";}
complex::complex(constcomplex & z) {re=z.re;im=z.im;cout<<"Constructor copiereptrcomplex(";
cout<<re<<","<<im<<")\n";} inline double complex::modul() { return sqrt(re*re+im*im); }

Supraincarcareaoperatorilor

58

CAP. 3

3.6. SUPRAINCARCAREA OPERATORULUI DE ATRIBUIRE =double complex::arg() {double a; if (re==0 &&


im==0) return (double)0; if (im==0) if (re>0) return 0.0; else return PI; if (re==0) if (im==0) return PI/2;
else return (3*PI)/2; a=atan(im/re); if (re<0) return PI+a; if (im<0) return 2*PI+a; return a; }inline void
complex::ipi() { im++; } inline void complex::dpi() { im--; }
Supraincarcareaoperatorilor

59

CAP. 3

3.6. SUPRAINCARCAREA OPERATORULUI DE ATRIBUIRE =complex operator +(constcomplex &a,


constcomplex &b) {complex z; z.re=a.re+b.re; z.im=a.im+b.im; return z; } complex operator +
(constdouble d, constcomplex &a) {complex z;z.re=d+a.re;z.im=a.im;returnz;} complex operator +
(constintd, constcomplex &a) {complex z;z.re=d+a.re;z.im=a.im;returnz;} complex operator +
(constcomplex &a, constdouble d) {complex z;z.re=d+a.re;z.im=a.im;returnz;} complex
complex::operator-(constcomplex &a) const{complex z;z.re=re-a.re;z.im=im-a.im;returnz;} complex
operator *(constcomplex &x,constcomplex &y) {complex z;z.re=x.re*y.re-x.im*y.im;
z.im=x.re*y.im+x.im*y.re;returnz;}

Supraincarcareaoperatorilor

60

CAP. 3

3.6. SUPRAINCARCAREA OPERATORULUI DE ATRIBUIRE =complex complex::operator *(constcomplex x)


const{complex z;z.re=re*x.re-im*x.im;z.im=re*x.im+im*x.re;returnz;} complex & complex::operator +()
const{return *this;} complex complex::operator -() const{complex z;z.re=-re;z.im=-im;return z;}complex
& complex::operator=(constcomplex &a){re=a.re;im=a.im;return *this;} // returnează obiectul curent

Supraincarcareaoperatorilor

61

CAP. 3

3.6. SUPRAINCARCAREA OPERATORULUI DE ATRIBUIRE =complex & complex::operator+=(constcomplex


&x) {double re1=re*x.re-im*x.im;doubleim1=re*x.im+im*x.re; re=re1; im=im1;return *this;} complex
complex::operator+=(constdouble d) {re+=d; return *this;} complex complex::operator-=(constcomplex
&x) {re-=x.re;im-=x.im; return *this;} complex &complex::operator /= (constcomplex &z) {double
numitor=z.re*z.re+z.im*z.im; double re1=(double)(re*z.re+im*z.im)/numitor; double im1=(double)
(im*z.re-re*z.im)/numitor; re=re1; im=im1;return *this;}

Supraincarcareaoperatorilor

62

CAP. 3

3.6. SUPRAINCARCAREA OPERATORULUI DE ATRIBUIRE =complex & complex::operator++() //forma


prefixata {cout<<"F. prefixata!\n";re++; return *this;} complex complex::operator ++ (int) //forma
postfixata { cout<<"F. postfixata!\n";complexz=*this; re++; return z;} complex complex::operator--()
{re--; return *this;} complex complex::operator ! () { complex w; double d,e; if ((d=modul())==0) return
w; e=arg();d=sqrt(d); e=e/2;w.re=d*cos(e);w.im=d*sin(e);return w;}
PROGRAMAREACALCULATOARELORŞILIMBAJEDE PROGRAMAREII

Supraincarcareaoperatorilor

63

CAP. 3

3.6. SUPRAINCARCAREA OPERATORULUI DE ATRIBUIRE =intcomplex::operator==(complex &x) {return


re==x.re && im==x.im;} intoperator==(complex &x, complex &y) {return (x.re==y.re && x.im==y.im);}
intcomplex::operator!=(complex &x) {return !(re==x.re && im==x.im);} intoperator!=(complex &x,
complex &y) {return !(x.re==y.re && x.im==y.im);} ostream&operator<<(ostream&ecran, constcomplex
&z) {ecran<<"("<<z.re; if (z.im>=0) ecran<<'+';ecran<<z.im<<"*i)"; return ecran;}
istream&operator>>(istream&tastatura, complex &z) {tastatura>>z.re>>z.im;returntastatura;}

Supraincarcareaoperatorilor

64

CAP. 3

3.6. SUPRAINCARCAREA OPERATORULUI DE ATRIBUIRE =//FISIERUL de test#include


"complex.cpp"#include <conio.h>#include <stdio.h>complex a(2.0, -6.0), b;main(){ cout<<"Intrarein
main\n";complex x(3,7), y(-1, 28), z;
cout<<"b="<<b<<'\n';cout<<"x="<<x<<'\n';cout<<"y="<<y<<'\n';cout<<"z="<<z<<'\n';
cout<<"a="<<a<<'\n';cout<<"a++="<<a++<<'\n';cout<<"++a="<<++a<<'\n';

Supraincarcareaoperatorilor

65

CAP. 3

3.6. SUPRAINCARCAREA OPERATORULUI DE ATRIBUIRE =printf("Pentrucontinuareintroduun car!\n");


getch();{ complex w; cout<<"Introducetiw:\n";cin>>w; cout<<"w cititeste: "<<w<<'\n';w.ipi();
cout<<"Dupaincrem. p. imag:"<<w<<'\n';w.dpi(); cout<<"Dupadecrem. p.
imag:"<<w<<'\n';cout<<"Modululluiw este:"<<w.arg()<<'\n';cout<<"Argumentulluiw
este:"<<w.arg()<<'\n';printf("Pentrucontinuareintroduun car!\n"); char rasp;cout<<"Se iesedin
bloculinterior!\n";}

Supraincarcareaoperatorilor

66

CAP. 3

3.6. SUPRAINCARCAREA OPERATORULUI DE ATRIBUIRE =printf("Pentrucontinuareintroduun


car!\n");getch(); cout<<"a="<<a<<'\n'; ++a; cout<<"Dupa increm. p. reale: "<<a<<'\n'; --a;
cout<<"Dupadecrem. p. reale: "<<a<<'\n'; a=x;cout<<"x="<<x<<'\n';cout<<"Dupaatribuire:
a="<<a<<'\n';getch(); a=x++;cout<<"a = "<<a<<'\n';complexk1=a;cout<<"k="<<k1<<'\n'; a=++x;cout<<"a
= "<<a<<'\n'; complex k=a;cout<<"k="<<k<<'\n';getch(); k=-a;cout<<"-unaraplicatlui
k:"<<k<<'\n';cout<<"-k="<<-k<<'\n'; k=x+y;cout<<x<<" + "<<y<<" = "<<k<<'\n';getch(); k=4+x;cout<<" 4 +
"<< x <<" ="<<4+x<<'\n';k=a*x; cout<<a<<" * "<<x<<" = "<<k<<'\n'; }

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

3.6. SUPRAINCARCAREA OPERATORULUI DE ATRIBUIRE =b) Se construieşte un proiect. De exemplu, dacă


se lucrează sub un mediu integrat, cum ar fi BorlandC, se crează cele trei fişiere (fractie.hcare conţine
declararea clasei, fractie.cppcare implementează metodele clasei şi fişierul de test (test_fractie.cpp)).
Fişierul header fractie.h va fi inclus atât în fractie.cpp, cât şi în test_fractie.cpp. Din meniul “Project” se
selectează “Open Project“, apoi comanda “Add item…”, care permite adăugarea fişierelor fractie.cpp şi
test_fractie.cpp.

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:

#ifndef_fractie_h#include "fractie.h" #define _fractie_h#endif

70

CAP. 3

To be continued…

Supraincarcareaoperatorilor

Supraincarcareaoperatorilor
71

1. Moduride supraincarcarea operatorilor2. Restrictiila supraincarcareaoperatorilor3.


Supraincarcareaoperatorilorunari4. Membriiconstantiaiclasei5.
Supraincarcareaoperatorilorinsertorsiextractor6. Supraincarcareaoperatoruluide atribuire=7.
Supraincarcareaoperatoruluide indexare[ ] 8. Supraincarcareaoperatorilornewsidelete9.
Supraincarcareaoperatorului( ) 10.Supraincarcarea operatorului-> 11.ConversiiCAP. 3

1.Conceptede bazaale programariiorientate


peobiecte2.Clasesiobiecte3.Supraincarcareaoperatorilor4.Creareaierarhiilorde clase5.Operatiide intrare/
iesirein limbajulC++6.Implementariale modelelorde
date7.Functiisiclasegenerice8.ExceptiisitratareaacestoraCuprinsulCursului

Programareacalculatoarelorşilimbajede programareII

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