[romanian book]c++ -cap 11

Click here to load reader

Post on 08-Jun-2015

1.016 views

Category:

Documents

4 download

Embed Size (px)

TRANSCRIPT

CAPITOLUL 11

Suprancrcarea operatorilor

SUPRANCRCAREA OPERATORILOR11.1. Moduri de suprancrcare a operatorilor 11.1.1. Suprancrcarea prin funcii membre 11.1.2. Suprancrcarea prin funcii prietene 11.2. Restricii la suprancrcarea operatorilor 11.3. Suprancrcarea operatorilor unari 11.4. Membrii constani ai unei clase 11.5. Suprancrcarea operatorilor insertor i extractor

1

11.6. Suprancrcarea operatorului de atribuire = 11.7. Suprancrcarea operatorului de indexare [ ] 11.8. Suprancrcarea operatorilor new i delete 11.9. Suprancrcarea operatorului ( ) 11.10. Suprancrcarea operatorului -> 11.11. Conversii

11.1. MODURI DE SUPRANCRCARE A OPERATORILORSuprancrcarea (supradefinirea, termenul overloading) operatorilor permite atribuirea de noi semnificaii operatorilor uzuali (operatorilor intlnii pentru tipurile de date predefinite). Aa cum am subliniat n numeroase rnduri, clasa reprezint un tip de date (o mulime de valori pentru care s-a adoptat un anumit mod de reprezentare i o mulime de operaii care pot fi aplicate acestora). Astfel, operatorul + folosete la adunarea a dou date de tip int, float sau double, ns aceluiai operator i se poate atribui semnificaia de "alipire" a dou obiecte de tipul ir, sau de adunare a dou obiecte de tipul complex, vector sau matrice. Observaie: Operatorii sunt deja supradefinii pentru a putea opera asupra mai multor tipuri de baz (de exemplu, operatorul + admite operanzi de tip int, dar i float sau double), sau pot avea seminificaii diferite (de exemplu, operatorul * poate fi folosit pentru nmulirea a doi operanzi numerici sau ca operator de defereniere, operatorul >> poate avea semnificaia de operator extractor sau operator de deplasare pe bit). Prin suprancrcarea operatorilor, operaiile care pot fi executate asupra instanelor (obiectelor) unei clase pot fi folosite ca i n cazul tipurilor de date predefinite. Exemplu: Pentru clasa punct (vezi capitolul 10), putem atribui operatorului + semnificaia: expresia a+b (a, b sunt obiecte din clasa punct) reprezint "suma" a dou puncte i este un punct ale crui coordonate sunt date de suma coordonatelor punctelor a i b. Astfel, supradefinirea operatorului + const n definrea unei funcii cu numele: operator +tip_val_ntoars operator op (lista_declar_parametri) {

// . . . .}

corpul funciei

Deci, limbajul C++ permite supradefinirea operatorului op prin definirea unei funcii numite operator op Funcia trebuie s poat accesa datele membre private ale clasei, deci supradefinirea operatorilor se poate realiza n dou moduri: printr-o funcie membr a clasei; printr-o funcie prieten a clasei.

11.1.1. SUPRANCRCAREA OPERATORILOR PRIN FUNCII MEMBREn situaia n care suprancrcarea operatorului + se realizeaz printr-o funcie membr, aceasta primete ca parametru implicit adresa obiectului curent (pentru care este apelat). Deci primul operand al operatorului este transmis implicit.153

CAPITOLUL 11

Suprancrcarea operatorilor

Exemplu:class punct{ double x, y; public:

// . . . . . .punct operator + (punct); };

//Metodele clasei punctpunct punct::operator + (punct a) { punct p; p.x=x + a.x; //echivalent cu p.x=this->x+a.x; p.y=y + a.y; //echivalent cu p.y=this->y+a.y; return p; } void main() { punct A(1.1, 2.2); A.afiare(); punct B(-5.5, -6.6); B.afiare(); punct C; C=A+B; C.afiare(); C=A+B+C; C.afiare(); }

Expresia C=A+B este interpretat ca C = A.operator + (B). Expresia C=A+B+C poate fi interpretat, n funcie 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).

11.1.2. SUPRANCRCAREA OPERATORILOR PRIN FUNCII PRIETENEFie clasa punct definit anterior. Reamintind faptul c funciile prietene au acces la membrii privai ai unei clase, ns nu primesc ca argument implicit pointerul ctre obiectul curent (this), s suprancrcm operatorul + printr-o funcie prieten a clasei punct:class punct{ double x, y; public:

// . . . . . .}; friend punct operator + (punct, punct);

//Metodele clasei punct.punct operator + (punct a, punct b) { punct p; p.x=a.x + b.x; p.y=a.y + b.y; return p; } void main() { punct A(1.1, 2.2); A.afiare(); punct B(-5.5, -6.6); B.afiare(); punct C; C=A+B; C.afiare(); C=A+B+C; C.afiare(); }

Expresia C=A+B este interpretat de compilator ca C=operator + (A, B). Expresia C=A+B+C este evaluat iinndu-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).

154

CAPITOLUL 11

Suprancrcarea operatorilor

Observaie: n exemplul anterior, transmiterea parametrilor ctre funcia prieten de suprancrcare a operatorului + se realizeaz prin valoare. Parametrii pot fi transmii i prin referin, pentru a evita crearea (n momentul apelului funciei) unor copii locale ale parametrilor efectivi n cei formali. La transmiterea parametrilor prin referin, funcia operator + are prototipul:punct operator + (punct &, punct &);

Pentru a proteja argumentele transmise prin referin la eventualele modificri, se poate folosi modificatorul de acces const: punct operator + (const punct &, const punct &);

11.2. RESTRICII LA SUPRANCRCAREA OPERATORILORSuprancrcarea operatorilor se poate realiza, deci, prin funcii membre sau funcii prietene. Dac suprancrcm acelai operator printr-o metod i printr-o funcie prieten, funcia prieten va avea, ntotdeauna, un parametru n plus fa de metod (deoarece funciei prietene nu i se transmite ca parametru implicit pointerul this). Totui, suprancrcarea operatorilor este supus urmtoarelor restricii: Se pot suprancrca doar operatorii existeni; nu se pot crea noi operatori. Nu se poate modifica aritatea (numrul de operanzi) operatorilor limbajului (operatorii unari nu pot fi supraincrcai ca operatori binari, i invers). Nu se poate modifica precedena i asociativitatea operatorilor. Dei operatorii suprancrcai pstreaz aritatea i precedena operatorilor predefinii, ei nu motenesc i comutativitatea acestora. Nu pot fi suprancrcai operatorii . ::? i : Observaii: n tabelul 2.8. (capitolul 2) sunt prezentai operatorii existeni, precedena i asociativitatea acestora. Dac operatorul = nu este suprancrcat, el are o semnificaie implicit. Operatorii , new delete [ ] -> i cast impun restricii suplimentare care vor fi discutate ulterior. Funcia operator trebuie s aib cel puin un argument (implicit sau explicit) de tipul clasei pentru care sa suprancrcat operatorul. Astfel: La suprancrcarea unui operator unar printr-o funcie membr a clasei, aceasta are un argument implicit de tipul clasei (obiectul care l apeleaz) i nici un argument explicit. La suprancrcarea operatorului unar printr-o funcie prieten, aceasta are un argument explicit de tipul clasei. La suprancrcarea unui operator binar printr-o funcie membr a clasei, aceasta are un argument implicit de tipul clasei (obiectul care l apeleaz) i un argument explicit. La suprancrcarea operatorului binar printr-o funcie prieten, aceasta are dou argumente explicite de tipul clasei. Se poate atribui unui operator orice semnificaie, ns este de dorit ca noua semnificaie s fie ct mai apropiat de semnificaia natural. De exemplu, pentru adunarea a dou obiecte se poate suprancrca operatorul * , dar este mai natural folosirea operatorului + cu semnificaia de adunare. n cazul supradefinirii operatorilor, nu se poate conta pe comutativitatea acestora. De exemplu, dac se suprancarc operatorul + pentru clasa complex printr-o funcie prieten a clasei complex: complex operator + (complex, double) Operatorul poate fi folosit n expresii cum ar fi: a+7.8 (a este obiect al clasei complex), dar nu n expresii ca: 7.8 + a. Dac un operator trebuie s primeasc ca prim parametru un tip predefinit, acesta nu poate fi supradefinit printr-o funcie membr. Operatorii care prezint i alte particulariti, vor fi tratai separat (vezi 11.7.,11.8., 11.10., 11.11.). n principiu, metodele care suprancarc un operator nu sunt statice. Excepia o constituie operatorii new i delete (vezi 11.8.). Diferena ntre forma prefixat i postfixat, la suprancrcarea operatorilor predefinii ++ i --, se poate face doar de anumite compilatoare (de exemplu, compilatorul de BorlandC, versiune>3.0, se poate face diferena).

155

CAPITOLUL 11

Suprancrcarea operatorilor

11.3. SUPRANCRCAREA OPERATORILOR UNARIOperatorii unari pot fi supradefinii printr-o funcie membr nestatic (fr parametri explicii) sau printr-o funcie prieten cu un parametru explicit de tipul clas. Ca exemplu, s suprancarcm operatorul unar ++ pentru clasa punct, pentru a putea fi folosit att n form prefixat, ct i postfixat (doar pentru compilatoarele care permit acest lucru!!). Vom folosi clasa punct implementat anterior, cu modificarea ca datele membre sunt de tipul int.class punct{ int x, y; public: // . . . punct & operator ++ (int ); punct & punct::operator++(); }; punct punct::operator ++ (int) {punct p=*this;x++; y++;return p;} punct & punct::operator++() {x++;y++; return *this;} void main() { punct A(11, 10); punct C=A++;A.afiare( ); C.afiare( ); punct C=++A;A.afiare( ); C.afiare( ); }

//forma postfixat //forma prefixat

11.4. MEMBRII CONSTANI AI UNEI CLASEAa cum s-a subliniat n capitolul 10, o clas poate avea membrii statici: date membru statice (figureaz ntrun singur exemplar pentru toate instanele clasei) sau metode statice (nu li se transmite pointerul this i pot modifica doar date membru statice). Deasemenea, o clas poate avea metode constante. O metod este declarat constant prin utilizarea modificatorului const n antetul ei (vezi exemplul de la pagina 150), dup lista parametrilor formali. Metodele constante nu modific obiectul pentru care sunt apelate. Ca oricror variabile de tip predefinit, i obiectelor de ti