Differences

This shows you the differences between two versions of the page.

Link to this comparison view

poo-is:laboratoare:04 [2020/09/12 12:04]
alexandru.ionita99
— (current)
Line 1: Line 1:
-====== Laboratorul 04: Functii Friend. Supradefinirea Operatorilor ====== 
- 
-In cadrul acestui laborator, vom aprofunda concepte de baza ale programarii obiectuale, cu precadere pe Functii Friend si Supradefinirea Operatorilor. Aceste concepte, odata intelese pe deplin, vor reprezenta un pas important catre stapanirea artei Programarii Orientate pe Obiecte! 
- 
-Ca referinte externe, recomandam urmatorul capitol din [[https://​discourse-production.oss-cn-shanghai.aliyuncs.com/​original/​3X/​2/​3/​2380479dcb8e375425884a10da232730bbc7f88d.pdf|Absolute C++]]: 
-  * Capitolul 8 (Chapter 8: Operator Overloading,​ Friends, and references) 
- 
- 
- 
-=====1. Functii Friend ===== 
-<note important>​O functie de tip **friend** este o functie ce se defineste in exteriorul clasei (**NU** se afla in **scopul/​contextul clasei**), dar are acces la toate atributele **private** sau **protected** ale clasei. 
-</​note>​ 
- 
-Sintaxa unei clasei friend arata in felul urmator: 
- 
-<code c++> 
-class NumeClasa 
-{ 
-   //cod 
-   ​friend TIP_RETURNAT NUME_FUNCTIE(ARGUMENTE);​ 
-   //cod 
-}; 
-</​code>​ 
- 
-Conform expresiei: Un exemplu de cod face cat 1000 de definitii, haideti sa analizam urmatoarea secventa. 
- 
- 
-====1.1. Definim Clasa ==== 
-<code c++> 
-class Distanta { 
-    private: 
-        int metri; 
-        ​ 
-    public: 
-        //​Constructor fara parametri (default) 
-        Distanta(); 
- 
-        // Functie Friend ​ 
-        // (ATENTIE: AICI DOAR SPECIFICAM CE FUNCTIE AVEM CA FRIEND - adunaCinciMetri) 
-        friend int adunaCinciMetri(Distanta);​ 
-}; 
-</​code>​ 
- 
-Functia **adunaCinciMetri()** primeste o distanta (un obiect de tip Distanta), la care aduna inca 5 metri, returnand noua valoare (int). ​ 
- 
-<note important>​Functia '​adunaCinciMetri'​ nu face parte din clasa '​Distanta',​ dar poate accesa campul **metri**. In cadrul clasei, doar se specifica relatia de '​friend'​ (de prietenie). Mai departe, vom vedea implementarea functiei '​adunaCinciMetri'​ in exteriorul clasei. </​note>​ 
- 
-<note tip>​Analogie:​ Doar fiindca un prieten/o prietena vine la voi in vizita, nu inseamna ca face parte din familie. Asa cum o functie de tip friend are acces la membri privati ai clasei, nu inseamna ca face parte din clasa. </​note>​ 
- 
-====1.2. ​ Implementam Constructorii,​ Metodele si Functiile Friend ==== 
-<code c++> 
-// Distanta - specifica clasa (scopul/​contextul apelului) 
-// Distanta() - constructor fara parametri 
-Distanta :: Distanta() 
-{ 
-  metri = 0; 
-} 
- 
-// DECLARAREA FUNCTIEI FRIEND 
-int adunaCinciMetri(Distanta d) { 
- 
-    //accesam atributele private ale clasei, din functie friend 
-    d.metri += 5; 
-    return d.metri; 
-} 
-</​code>​ 
-<note important>​A se observa diferenta dintre header-ul constructorului si cel al clasei Friend. Constructorul are '​atasat'​ si contextul (numele clasei), pe cand functia friend este de sine statatoare. **Asadar, o functie ar putea sa fie FRIEND cu mai multe clase. **</​note>​ 
- 
-<note important>​Functiile friend **NU** se mostenesc.</​note>​ 
- 
-<note tip>​Analogie:​ Doar fiindca voi sunteti prieteni cu o persoana, nu inseamna ca persoana aceea nu mai are alti prieteni la randul sau. De asemenea, prietenii parintilor vostri nu sunt neaparat si prietenii vostri (precum in viata reala, prietenii nu se mostenesc). Ducand acest exemplu mai departe, un prieten de-al vostru poate sa fie si prietenul '​dusmanului'​ vostru. Functiile **friend** pot duce la '​leak-uri'​ de informatii, asa cum un prieten poate '​scapa'​ o barfa despre voi unde nu trebuie. </​note>​ 
- 
-====1.3. Cum apelam? ==== 
- 
-<code c++> 
-int main() { 
-    Distanta D; // metri = 0 
-    cout << "​Distanta:​ " << adunaCinciMetri(D) << endl; 
-    return 0; 
-} 
-</​code>​ 
- 
-====1.4. Codul intreg ==== 
-Pentru a rula codul intreg, apasa [[https://​repl.it/​@thesergiu/​lab3friend1#​main.cpp|aici]]. 
- 
- 
-<code c++> 
-#include <​iostream>​ 
-using namespace std; 
- 
-class Distanta { 
-    private: 
-        int metri; 
-        ​ 
-    public: 
-        //​Constructor fara parametri (default) 
-        Distanta(); 
- 
-        // Functie Friend ​ 
-        // (ATENTIE: AICI DOAR SPECIFICAM CE FUNCTIE AVEM CA FRIEND - adunaCinciMetri) 
-        friend int adunaCinciMetri(Distanta);​ 
-}; 
- 
-// Distanta - specifica clasa (scopul/​contextul apelului) 
-// Distanta() - constructor fara parametri 
-Distanta :: Distanta() 
-{ 
-  metri = 0; 
-} 
- 
-// DECLARAREA FUNCTIEI FRIEND 
-int adunaCinciMetri(Distanta d) { 
- 
-    //accesam atributele private ale clasei, din functie friend 
-    d.metri += 5; 
-    return d.metri; 
-} 
- 
-int main() { 
-    Distanta D; 
-    cout << "​Distanta:​ " << adunaCinciMetri(D) << endl; 
-    return 0; 
-} 
-</​code>​ 
- 
-=====2. Supradefinirea Operatorilor ===== 
- 
-<note important>​ 
-Functiile operator constituie un tip special de functii. Sunt utilizate pentru redefinirea operatorilor si pentru alte tipuri de date (definite de utilizator) in afara celor de baza. 
-</​note>​ 
- 
-Miza finala este sa putem manipula obiecte definite de noi, in aceeasi maniera in care lucram cu variabile ce sunt tipuri de baza: 
- 
-<code c++> 
-// Instantiem obiecte 
-ClasaDefinitaDeNoi obj1(/​*argumente constructor*/​),​ obj2(/​*argumente constructor*/​);​ 
-ClasaDefinitaDeNoi obj3 = obj1 + obj2; 
-// Afisam obiecte 
-cout << obj3 << endl; 
- 
-dimensiune = 3; 
-// Alocam memorie pentru un vector ce contine elemente de tip ClasaDefinitaDeNoi 
-ClasaDefinitaDeNoi *vectObj = new ClasaDefinitaDeNoi [dimensiune];​ 
-//etc 
-</​code>​ 
- 
-====2.1. Sintaxa Generala ==== 
-<code c++> 
-class NumeleClasei { 
-    ... .. ... 
-    public: 
-       ​TIP_RETURNAT operator symbol (argumente);​ 
-           ... .. ... 
-    ... .. ... 
-}; 
- 
-TIP_RETURNAT NumeleClasei::​operator symbol(argumente) 
-{ 
-    ... 
-} 
-</​code>​ 
- 
-====2.2. De ce se supradefinesc operatorii? ==== 
- 
-O clasa se poate defini împreuna cu un set de operatori asociati, obtinuti prin supraîncarcarea operatorilor existenti. In acest fel, se efectueaza operatii specifice noului tip, la fel de simplu ca în cazul tipurilor standard, printr-o semantica naturala (ex: adunarea a doua numere complexe). \\ 
- 
-Procedeul consta în definirea unei functii cu numele: **operator <​symbol>​**\\ 
- 
- 
-Tipurile de operatori sunt:  
-  * Operatori **unari** (cu un argument/​operand). Ex: ++b, b++, -a(cu sensul de inversul lui a) 
-  * Operatori **binari** (cu doua argumente/​operanzi). Ex: a + b, c == d, a = b 
- 
- 
-<note warning> 
-Toti operatorii pot fi supradefiniti cu urmatoarele cateva exceptii: 
-  * operatorul de acces la membrii clasei ** . ** 
-  * operatorul de rezolutie **::​** ​ 
-  * operatorul conditional ** ?  : ** 
-  * operatorul **sizeof** 
-</​note>​ 
- 
-==== Supradefinirea Operatorilor Unari ==== 
-In exemplul de mai jos, vom vedeam ambele tipuri de supradefinire pentru operatorul **++**. Considerentele si rationamentele supradefinirii sunt abordate in sectiunile urmatoare. 
- 
-<code c++> 
-// Supradefinirea ++ ca '​prefix'​ si '​postfix'​ 
- 
-class NumaramBani ​ 
-{ 
-private: 
-    int lei; 
-public: 
-    // Constructor care initializeaza lei = 5 
-    Count() : lei(5) {} 
- 
-    // Supradefinim ++ ca prefix; adica, ++obiect; 
-    void operator ++ () { 
-        ++lei; 
-    } 
- 
-    // Supradefinim ++ ca postfix; adica, obiect++ 
-    void operator ++ (int) { 
-        ++value; 
-    } 
- 
-    void afisare() { 
-        cout << "lei: " << lei << endl; 
-    } 
-}; 
- 
-int main() { 
-    NumaramBani numarator; 
- 
-    // Apelam functia "void operator ++ ()" ​ 
-    ++numarator;​ 
- 
-    numarator.afisare();​ 
-    return 0; 
-} 
-</​code>​ 
-In exemplul de mai sus, remarcam conventia postfix 'void operator ++(int)'​ pentru a distinge dintre cele 2 tipuri de incrementare unara. Conventia este subinteleasa de limbajul C++, permitand compilatorului sa aplice operatia potrivita aferenta incrementarii. 
- 
-==== Supradefinirea Operatorilor Binari ==== 
-In cazul Operatorilor Binari, avem 2 abordari distincte, care indeplinesc acelasi scop general, anume: 
-  - Functii Membre 
-  - Functii Friend 
- 
-Cu toate acestea, exista diferente de interpretare din partea compilatorului dintre cele 2 abordari. 
- 
-Pentru a exemplifica ideile principale, vom lucra cu urmatoarea clasa ce implementeaza functionalitatile unui numar complex. 
- 
-<code c++> 
-class complex 
-{ 
-private: 
-      double real; 
-      double imaginar;  ​ 
-public: 
-    // Aici definim Constructori si Operatori 
-}; 
-</​code>​ 
- 
-=== Supradefinirea operatorilor prin Functii Membre === 
-In cazul functiilor membre apar urmatoarele constrangeri:​ 
-  - Operatorul supradefinit trebuie sa fie o functie membra a operatorului stang. 
-  - Operatorul stang devine implicit obiectul *this. 
-  - Ceilalti operanzi devin parametri ai functiei 
- 
-== Operanzi ce returneaza un obiect == 
-Definim in felul urmator: 
-<code c++> 
-complex&​ operator +(const complex&​ c); 
-complex&​ operator -(const complex&​ c); 
-complex&​ operator *(const complex&​ c); 
-complex&​ operator /(const complex&​ c); 
-</​code>​ 
- 
-Exemplu de implementare:​ 
-<code c++> 
-complex&​ complex::​operator +(const complex&​ c) 
-{ 
-    this->​real += c.real; 
-    this->​imaginar += c.imaginar; 
-    return *this; 
-} 
-</​code>​ 
- 
-== Operanzi booleni == 
-Definim in felul urmator: 
-<code c++> 
-bool operator >(const complex&​ c);  ​ 
-bool operator <(const complex&​ c);  ​ 
-bool operator ==(const complex&​ c);  
-bool operator !=(const complex&​ c);  
-</​code>​ 
- 
-Exemplu de implementare:​ 
-<code c++> 
-bool complex::​operator ==(const complex&​ c) 
-{ 
-  if(real == c.real && imaginar == c.imaginar) 
-      return true; 
-  else  
-      return false; ​   ​ 
-} 
-</​code>​ 
- 
-<note important>​**Atentie!** In ceea ce priveste numerele complexe, pentru a determina ce numar este mai mare sau mai mic, folosim metode matematice (aplificare conjugata, inmultiri etc).</​note>​ 
- 
- 
-=== Supradefinirea operatorilor prin Functii Friend === 
-In cazul functiilor friend, eliminam din constrangerile ce apar la functii membre: 
-  * Nu vom mai avea *this, acesta fiind inlocuit de operandul stang. 
-  * Orice referinta catre *this poate fi inlocuita cu primul operand (operandul stang). 
-  * Nu vom mai fi restrictionati de tipul operandului stang pentru a efectua operatia. 
-  * Mentionam ca Functia Friend este 'mai lenta' din punct de vedere viteza a rularii codului. 
- 
-== Operanzi ce returneaza un obiect == 
-Definim in felul urmator: 
-<code c++> 
-friend const complex operator +(const complex&​ c1, const complex & c2); 
-friend const complex operator -(const complex&​ c1, const complex & c2); 
-friend const complex operator *(const complex&​ c1, const complex & c2);      ​ 
-friend const complex operator /(const complex&​ c1, const complex&​ c2); 
- 
-friend const complex operator -=(const complex&​ c1, const complex & c2); 
- 
-// Operator citire 
-friend istream&​ operator >>​(istream&​ citire, complex&​ c); 
-// Operator afisare  ​ 
-friend ostream&​ operator <<​(ostream&​ afisare, const complex&​ c);  
-</​code>​ 
- 
-Exemplu de implementare:​ 
-<code c++> 
-const complex operator +(const complex&​ c1, const complex&​ c2) 
-{ 
-   int Real; 
-   int Imaginar; 
-   Real = c1.real + c2.real; 
-   ​Imaginar = c1.imaginar + c2.imaginar;​ 
-   ​return complex(Real,​ Imaginar); 
-} 
- 
-istream&​ operator >>​(istream&​ citire, ​ complex&​ c) 
-{ 
-   ​citire >> c.real >> c.imaginar; 
-   ​return citire; 
-} 
- 
-ostream&​ operator <<​(ostream&​ afisare, const complex&​ c) 
-{ 
-   ​if(c.imaginar > 0) 
-   { 
-     ​afisare << c.real << " " << "​+"​ << c.imaginar <<"​i"<< ​ endl; 
-   } 
-   ​else ​ 
-   { 
-     ​afisare << c.real << " " << c.imaginar << "​i"​ << endl; 
-   } 
-   ​return afisare; 
-} 
-</​code>​ 
-== Operanzi booleni == 
-Definim in felul urmator: 
-<code c++> 
-friend bool operator == (const complex&​ a, const complex&​ b) 
-</​code>​ 
- 
-Exemplu de implementare:​ 
-<code c++> 
-bool operator == (const complex&​ a, const complex&​ b) 
-{ 
-  if (a.real == b.real && a.imaginar == b.imaginar) 
-  { 
-    return true; 
-  } 
-  else return false; 
-} 
-</​code>​ 
- 
- 
-====2.3. Dupa ce reguli se realizeaza supradefinirea?​ ==== 
- 
-**1.** Se pot supradefini numai operatori existenti, deci simbolul asociat functiei operator trebuie sa fie deja definit ca operator pentru tipurile standard. Nu e permisa introducerea unor simboluri noi de operatori (ex |x|).  
- 
-**2.** Nu se pot modifica: 
-            * pluralitatea (un operator unar nu poate fi supradefinit ca unul binar sau invers) 
-            * precedenta 
-            * asociativitatea. ​ 
- 
-**3.** Operatorul definit ca functie **friend** trebuie sa aiba cel putin un parametru de tipul clasa caruia ii este asociat operatorul respectiv. Aceasta restrictie implica faptul ca supradefinirea operatorilor e posibila numai pentru tipurile clasa definite in program, pentru tipurile standard operatorii isi pastreaza definitia. ​ 
- 
-<code cpp> 
-//Operator + pentru tipul complex, cu al doilea operand de tip double 
- 
-//Varianta functie membra 
-const complex complex:: operator + (const double& a) const 
-{ 
- ​return complex (re+a , im); 
-} 
- 
-//Varianta functie friend 
-friend const complex operator + (const complex&​ c1, const double& c2) 
-{ 
- ​return complex (c1.re+c2, c1.im); 
-} 
- 
-</​code>​ 
- 
-**4.** Pentru a putea fi transformata in functie membra, un operator definit ca functie **friend** trebuie sa aiba ca prim parametru un obiect de tipul clasei. 
- 
-<code cpp> 
-// Operatorul +, ce are parametrii double si complex 
-friend const complex operator + (const double& c1, const complex&​ c2) 
-{ 
- ​return complex (c1+c2.re, c2.im) 
-} 
- 
-</​code>​ 
- 
-<note important>​Nu putem transforma functia de mai sus in **functie membra**, deoarece ar insemna sa supradefinim operatorul + pentru tipul standard double</​note>​ 
- 
-**5.**Functiile operator pot fi implementate ca si functii membre ale clasei sau ca si functii prietene ale clasei, atunci cand este necesar. 
- 
-<code cpp> 
-//Operator + pentru tipul complex 
- 
-//Varianta ca functie membra 
-const complex complex::​operator + (const complex&​ a ) const 
-{ 
- ​return complex (re + a.re, im + a.im) 
-} 
- 
-//Varianta ca functie friend (preferata, deoarece mimeaza cel mai bine +) 
-friend const complex operator + (const complex & a const complex & b) 
-{ 
- ​return complex (a.re + b. re, a.im + b.im) 
-} 
-</​code>​ 
- 
-<note important>​ In particular, pentru operatorii: **=** ,**[]**, **()**, **->** functia operator trebuie sa fie membra a clasei. ​ 
-</​note>​ 
- 
-====2.4. Cum arata supradefinirea?​ ==== 
-!! EXEMPLE COD (Operatori membri + FRIEND) 
- 
-====2.5. Observatii Generale ====            ​ 
-<note warning> Operatorul ** = ** este generat intotdeauna de catre compilator. Totusi, este indicat ca orice clasa sa defineasca propriul operator de atribuire, pentru a evita confuziile si comportamentele nedorite/​default,​ mai ales in cazul alocarii si eliberarii de memorie (ex: **copii superficiale** in cazul atributelor de tip **pointer**)</​note>​ 
- 
-  * Pentru un __operator binar__ **op**, expresia **x op y** este interpretata:​ 
-<code c++> 
-x.operator op(y); // functie membr 
-</​code>​ 
-SAU 
-<code c++> 
-operator op(x,y); // functie friend 
-</​code>​ 
-  *  Pentru un __operator unar__ **op**, expresia **x op** sau **op x** este interpretata:​ 
- 
-<code c++> 
-x.operator op(); //functie membra 
-</​code>​ 
-SAU 
-<code c++> 
-operator op(x); //functie friend 
-</​code>​ 
- 
-====2.6. Observatii legate de tipul argumentelor si tipul returnat ====  ​ 
- 
-Urmatoarele considerente tin de 'o buna conduita'​ in programarea obiectuala. Exista si alte abordari 'care merg', dar dorim sa clarificam cele mai bune standarde. Aceste concepte sunt complexe, iar mai jos aveti doar o prezentare a acestora. Pentru o intelegere mai buna, inspectati resursele externe.\\ 
- 
-Este recomandat ca operatorii sa fie supradefiniti astfel: \\ 
- 
-^ Operatori ​                   ^ Supradefiniti ca:                 ^ 
-|toti operatorii unari         | functii membre ​                   | 
-| =, [], ()                    | **trebuie** sa fie functii membre | 
-| +=, -=, *=, ...              | functii membre ​                   | 
-|toti ceilalti operatori binari| functii friend ​                   | 
- 
- 
-**1.**Daca se doreste citirea dintr-un parametru/​argument fara modificarea acestuia, atunci ar trebui transmis in functie ca referinta constanta (astfel voi putea sa transmit ca parametri si obiecte temporare). 
- 
-<code cpp> 
-//Operator = pentru numere complexe 
-complex&​ operator = (const complex&​ a ) 
-{ 
- re = a.re; 
- im = a.im; 
- ​return *this; 
-} 
- 
-</​code>​ 
- 
-<note tip>​Implementarea de mai sus permite o atribuire de tipul:\\ **complex c;\\ c = complex(1,​3)**\\ Daca parametrul ar fi fost o referinta **neconstanta**,​ compilatorul **nu** ar fi permis transmiterea unui obiect temporar prin referinta</​note>​ 
- 
-Apelul **operatorului +** va arata asa: 
-<code c++> ​ 
-// Exemplu 
-c = a + b; 
- 
-///SAU/// 
- 
-c = a.operator + (b) 
-</​code>  ​ 
- 
-<note tip>​Operatiile **aritmetice (+,-,etc)** si cele **logice(==,>,​etc)** nu vor modifica valorile parametrilor. In acest caz, daca operatorul este implementat ca functie membra va fi o functie membra constanta (nu modifica atributele obiectelor care apeleaza functia)\\ \\ Exemplu: const complex complex::​operator - (const complex&​ a ) **const** </​note>​ 
- 
- 
-**2.** Tipul returnat depinde de '​intelesul'​ operatorului:​ 
-  *  Daca efectul operatorului este acela de a produce o noua valoare, va trebui sa fie creat/​generat un nou obiect si returnat prin valoare. 
-<code cpp> 
-//Operator - pentru tipul complex 
- 
-//Varianta ca functie membra 
-const complex complex::​operator - (const complex&​ a ) const 
-{ 
- ​return complex (re - a.re, im - a.im) //este creat un nou obiect si returnat prin valoare 
-} 
- 
-//Varianta ca functie friend 
-friend const complex operator - (const complex & a const complex & b) 
-{ 
- ​return complex (a.re - b. re, a.im - b.im) //este creat un nou obiect si returnat prin valoare 
-} 
-</​code>​ 
- 
-Acest nou obiect este retunat prin valoare ca si constanta, astfel incat rezultatul sa nu poata fi modificat in cadrul unei operatii in care el ar fi operandul din stanga( lvalue): 
- 
-Ganditi-va la tipurile de date de baza; nu avem voie sa facem asa ceva: 
-<code c++> 
-int a=2,​b=3,​c=6;​ 
-a+b=d; //ERROR non-lvalue in assignment ​ 
-</​code>​ 
- 
-<​note>​ 
-De ce nu? S-ar modifica un obiect temporar – iar modificarea s-ar pierde: 
-</​note>​ 
- 
-<​code>​ 
-complex a(2,​2),​b(2,​2);​ 
-(a-b).modifica(7,​7);​ //​modificarea asupra obiectului returnat de + se pierde. 
-</​code>​ 
- 
-<note important>​ 
-Este de preferat sa pot apela doar functii constante – de tip afisare, etc care garanteaza ca nu vor face modificari. 
-</​note>​ 
- 
-**3. **Pentru a permite ca rezultatul atribuirii sa fie folosit intr-o expresie in lant: a=b=c, este asteptat ca operatorul sa intoarca o referinta catre operandul de tip lvalue pe care tocmai l-a modificat. 
- 
-<code cpp> 
-complex&​ operator = (const complex&​ a) 
-{ 
- re = a.re; 
- im = a.im; 
- ​return *this; //​returneaza o referita catre obiectul care apeleaza functia (a = b <=> a.operator = (b)) 
-} 
-</​code>​ 
- 
-Atribuirea se face de la dreapta la stanga: a=(b=c), deci nu ar trebui neaparat intoarsa o referinta constanta. ​ 
- 
-Mai mult, uneori se doreste realizarea unei modificari asupra obiectului care tocmai a fost modificat prin atribuire: ​ 
-<​code>​ 
-(a=b).modifica();​ 
-</​code>​ 
-Modificarea sa trebuie pastrata in **a**. In acest caz, tipul returnat de toti operatorii de atribuire ar trebui sa fie o **referinta neconstanta** catre lvalue.\\ 
- 
-**4. ** Operatorii de incrementare si decrementare atat in versiune prefixata cat si in versiune postfixata modifica obiectul, deci nu pot sa fie functii constante. 
-  * versiunea prefixata (++a) returneaza valoarea obiectului **dupa** modificare: return *this; (ca referinta). 
-  * versiunea postfixata intoarce valoarea **inainte** de modificare, ceea ce inseamna crearea unui nou obiect, deci va intoarce un obiect prin valoare. 
- 
-<code cpp> 
-//Forma prefixata 
-const complex&​ operator ++()  
-{ 
- ​this->​re++;​ 
- ​this->​im++;​ 
- ​return *this //​returneaza referinta catre obiectul curent, MODIFICAT 
-} 
- 
-//Forma postfixata 
-const complex operator++(int i) // i reprezinta formularea standard ce diferentiaza cei 2 operatori 
-{ 
- ​complex aux(*this) //fac o copie a obiectului nemodificat,​ folosind constructorul de copiere 
- ​this->​re++;​ //modific valorile sale 
- ​this->​im++;​ 
- ​return aux; //returnez COPIA cu valorile originale, in timp ce obiectul in sine se modifica ​ 
-} 
-</​code>​ 
- 
-//​Rezultatul intors ar trebui sa fie const sau nu?//\\ 
-Daca nu este const si avem ceva de genul: 
-  * (++a).funct(),​ funct() va opera asupra lui a (o referinta) 
-  * dar in cazul (a++).funct(),​ va opera asupra unui obiect temporar returnat de varianta postfixata a operatorului. Obiectele temporare sunt constante, ceea ce va fi sesizat de compilator (nu pot chema decat functii const). 
-**Cea mai buna solutie** e ca **amandoua** versiunile sa returneze o **constanta** (sau versiunea prefixata returneaza non const si cea postfixata const) 
- 
- 
-**5. ** Pentru operatorii logici, toata lumea se asteapta sa primeasca in cel mai rau caz un rezultat de tip **int** si in cel mai bun caz un rezultat de tip **bool**. 
- 
-<code cpp> 
-//​Operatorul == pentru complex, ca functie friend 
- 
-//​Returneaza int 
-friend int operator == (const complex&​ a, const complex&​ b) 
- 
- if (a.re == b.re && a.im = b.im) 
-   ​return 1; 
- else 
-   ​return 0; 
-} 
- 
-//​Returneaza bool 
-friend bool operator == (const complex&​ a, const complex&​ b) 
- 
- ​return ((a.re == b.re) && (a.im == b.im)) 
-} 
- 
-</​code>​ 
  
poo-is/laboratoare/04.1599901452.txt.gz · Last modified: 2020/09/12 12:04 by alexandru.ionita99
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0