Differences

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

Link to this comparison view

poo-is-ab:laboratoare:04 [2024/10/21 11:30]
razvan.cristea0106 [Supraîncărcarea operatorilor]
poo-is-ab:laboratoare:04 [2025/01/19 22:28] (current)
razvan.cristea0106
Line 31: Line 31:
 **Operatorul Ternar**: există un **singur** operator ternar în C++, cunoscut sub numele de **operator condițional (?:)**. Acesta utilizează **trei** operanzi și este folosit pentru a evalua o condiție și a alege între două valori, în funcție de rezultatul acelei condiții. **Operatorul Ternar**: există un **singur** operator ternar în C++, cunoscut sub numele de **operator condițional (?:)**. Acesta utilizează **trei** operanzi și este folosit pentru a evalua o condiție și a alege între două valori, în funcție de rezultatul acelei condiții.
  
-În continuare vom prezenta un tabel cu operatorii ​din C++ unde vom vedea atât simbolurile cât și modul de asociere al acestora.+În continuare vom prezenta un tabel cu operatorii ​existenți în limbajul ​C++ pentru a putea vedea atât simbolurile cât și modul de asociere ​(aplicare) ​al acestora.
  
 ^        Categoria de operatori ​       ^       ​Simbolurile operatorilor ​            ​^ ​                Mod de asociere (aplicare) ​             ^ ^        Categoria de operatori ​       ^       ​Simbolurile operatorilor ​            ​^ ​                Mod de asociere (aplicare) ​             ^
-| **Primari** ​           | (), [], ., %%->%% |         ​stânga - dreapta ​        |+| **Primari** ​           | ( ), [ ], ., %%->%% |         ​stânga - dreapta ​        |
 | **Unari** ​             | ++, %%--%%, -, !, ~, (tip), &, *, sizeof |         ​**dreapta - stânga** ​        | | **Unari** ​             | ++, %%--%%, -, !, ~, (tip), &, *, sizeof |         ​**dreapta - stânga** ​        |
 | **Multiplicativi** ​    | *, /, %                         ​| ​        ​stânga - dreapta ​        | | **Multiplicativi** ​    | *, /, %                         ​| ​        ​stânga - dreapta ​        |
Line 120: Line 120:
 În mod evident puteam declara și implementa o metodă simplă de afișare în loc să optăm pentru o funcție **friend**. Trebuie însă menționat faptul că este doar un exemplu didactic pentru a putea înțelege cum putem folosi funcțiile **friend** în limbajul C++. În mod evident puteam declara și implementa o metodă simplă de afișare în loc să optăm pentru o funcție **friend**. Trebuie însă menționat faptul că este doar un exemplu didactic pentru a putea înțelege cum putem folosi funcțiile **friend** în limbajul C++.
  
-<note warning>​Deși sunt declarate în interiorul clasei funcțiile ​**friend** se numesc **funcții** și **nu metode** datorită faptului că nu primesc **pointerul this** în lista de parametri. Cuvântul cheie **friend** se utilizează **doar** la declararea funcției pentru a înștința compilatorul că este vorba despre o **funcție** și **nu** despre o **metodă**,​ iar implementarea acesteia este **identică** cu a unei **funcții clasice din C++**.</​note>​+<note warning>​Deși sunt declarate în interiorul clasei ​**funcțiile friend** se numesc **funcții** și **nu metode** datorită faptului că **nu** primesc **pointerul this** în lista de parametri. Cuvântul cheie **friend** se utilizează **doar** la declararea funcției pentru a înștința compilatorul că este vorba despre o **funcție** și **nu** despre o **metodă**,​ iar implementarea acesteia este **identică** cu a unei **funcții clasice din C++**.</​note>​
  
 Vom folosi foarte mult acest tip de funcții după cum vom vedea în cele ce urmează la supraîncărcarea operatorilor limbajului C++. Vom folosi foarte mult acest tip de funcții după cum vom vedea în cele ce urmează la supraîncărcarea operatorilor limbajului C++.
Line 128: Line 128:
 În această secțiune vom învăța cum vom putea specializa diverși operatori pentru o clasă astfel încât obiectele acesteia să se comporte similar cu variabilele care sunt declarate folosind **tipuri de date primitive (int, float, char, long, double, etc.)**. Clasa cu care vom lucra este **NrComplex** în care ne dorim să punem în evidență diferite variante de operatori supraîncărcați. În această secțiune vom învăța cum vom putea specializa diverși operatori pentru o clasă astfel încât obiectele acesteia să se comporte similar cu variabilele care sunt declarate folosind **tipuri de date primitive (int, float, char, long, double, etc.)**. Clasa cu care vom lucra este **NrComplex** în care ne dorim să punem în evidență diferite variante de operatori supraîncărcați.
  
-Structura clasei **NrComplex** poate fi observata ​în codul de mai jos.+Structura clasei **NrComplex** poate fi observată ​în codul de mai jos.
  
 <code cpp> <code cpp>
Line 184: Line 184:
 <​note>​După cum am putut observa în fișierul **header** pentru clasa **NrComplex** am declarat un constructor cu parametri cu **valori implicite**. Acest **constructor special** ține locul de fapt a trei constructori. Dacă **nu** vom specifica niciun parametru câmpurile vor primi valoarea 0.0 care este cea **default**. Dacă specificăm un parametru atunci **doar** partea imaginară va primi valoarea 0.0 care este cea **implicită**.</​note>​ <​note>​După cum am putut observa în fișierul **header** pentru clasa **NrComplex** am declarat un constructor cu parametri cu **valori implicite**. Acest **constructor special** ține locul de fapt a trei constructori. Dacă **nu** vom specifica niciun parametru câmpurile vor primi valoarea 0.0 care este cea **default**. Dacă specificăm un parametru atunci **doar** partea imaginară va primi valoarea 0.0 care este cea **implicită**.</​note>​
  
-<note warning>​Atunci când definim **funcții** sau **metode** care conțin parametri cu **valori implicite**,​ este esențial ca acești parametri să fie plasați **după** parametrii fără valori implicite în lista de argumente. Dacă această regulă **nu** este respectată,​ compilatorul va genera o eroare, deoarece nu va putea să determine corect care dintre parametri trebuie să primească valoarea implicită și care valoare este furnizată explicit la apelul funcției. Această regulă asigură claritatea și predictibilitatea modului în care sunt procesate argumentele funcției.</​note>​+<note warning>​Atunci când definim **funcții** sau **metode** care conțin parametri cu **valori implicite**,​ este esențial ca acești parametri să fie plasați **după** parametrii fără valori implicite în lista de argumente. Dacă această regulă **nu** este respectată,​ compilatorul va genera o **eroare ​de ambiguitate**, deoarece ​**nu** va putea să determine ​**corect** care dintre parametri trebuie să primească valoarea implicită și care valoare este furnizată explicit la apelul funcției. Această regulă asigură ​**claritatea** și **predictibilitatea** modului în care sunt procesate argumentele funcției.</​note>​
  
 === Operatori supraîncărcați ca funcții membre în clasă === === Operatori supraîncărcați ca funcții membre în clasă ===
Line 245: Line 245:
 </​code>​ </​code>​
  
-<note important>​Se poate observa ca la **forma postfixată** avem un parametru de care **nu** ne folosim. Acel parametru este **doar** pentru a asigura **polimorfismul**,​ compilatorul ​facând ​distincția între cele două variante de operator de incrementare.</​note>​+<note important>​Se poate observa ca la **forma postfixată** avem un parametru de care **nu** ne folosim. Acel parametru este **doar** pentru a asigura **polimorfismul**,​ compilatorul ​făcând ​distincția între cele două variante de operator de incrementare.</​note>​
  
 Pentru **operatorul de decrementare** se aplică aceleași **exact** aceeași pași, încercați să îl implementați voi pentru a putea înțelege mai bine cum funcționează conceptul de **overloading**. Pentru **operatorul de decrementare** se aplică aceleași **exact** aceeași pași, încercați să îl implementați voi pentru a putea înțelege mai bine cum funcționează conceptul de **overloading**.
Line 299: Line 299:
 == Supraîncărcarea operatorilor == și != == == Supraîncărcarea operatorilor == și != ==
  
-**Operatorul %%==%%** este folosit pentru a testa egaliatetea dintre doi operanizi, deci prin urmare trebuie să returneze o valoare de adevăr (**true** sau **false**). Îl supraîncârcăm ca funcție membră, deoarece avem deja un parametru existent, și anume **pointerul this**, la care mai adăugăm un alt parametru care reprezintă **obiectul cu care facem comparația**.+**Operatorul %%==%%** este folosit pentru a testa egaliatetea dintre doi operanzi, deci prin urmare trebuie să returneze o valoare de adevăr (**true** sau **false**). Îl supraîncârcăm ca funcție membră, deoarece avem deja un parametru existent, și anume **pointerul this**, la care mai adăugăm un alt parametru care reprezintă **obiectul cu care facem comparația**.
  
 Același lucru putem spune și despre **operatorul %%!=%%**, numai că el face exact **opusul** a ceea ce face operatorul de testare a egalității între doi operanzi, adică verifică dacă valorile celor doi termeni sunt **diferite**. Același lucru putem spune și despre **operatorul %%!=%%**, numai că el face exact **opusul** a ceea ce face operatorul de testare a egalității între doi operanzi, adică verifică dacă valorile celor doi termeni sunt **diferite**.
Line 345: Line 345:
 bool NrComplex::​operator!=(const NrComplex&​ z) const bool NrComplex::​operator!=(const NrComplex&​ z) const
 { {
- return this->​real != z.real ​&& ​this->​imaginar != z.imaginar;+ return this->​real != z.real ​|| this->​imaginar != z.imaginar;
 } }
 </​code>​ </​code>​
Line 563: Line 563:
 ==== ==== ==== ====
  
-Codul cu implementările operatorilor prezentați pentru clasa **NrComplex** poate fi descărcat de {{:​poo-is-ab:​laboratoare:​complex_overloading.zip|aici}}.+Codul complet ​cu implementările operatorilor prezentați pentru clasa **NrComplex** poate fi descărcat de {{:​poo-is-ab:​laboratoare:​complex_overloading.zip|aici}}.
  
-<note warning>​În limbajul C++ **nu** este permisă supraîncărcarea ​operatorilor ​următori:+<note warning>​În limbajul C++ **nu** este permisă supraîncărcarea următorilor operatori:
   * de rezoluție **"::"​**   * de rezoluție **"::"​**
   * de acces la membrii unei clase/​structuri **"​."​**   * de acces la membrii unei clase/​structuri **"​."​**
Line 576: Line 576:
 ==== Concluzii ==== ==== Concluzii ====
  
-În cadrul acestui laborator, am descoperit **importanța supraîncărcării operatorilor** într-o clasă și modul în care acest proces ne permite să efectuăm diverse operații într-un mod **intuitiv**,​ la fel cum procedăm și cu **tipurile de date standard (int, float, char,...)**. Prin **supraîncărcarea operatorilor**,​ am reușit să **îmbunătățim lizibilitatea și ușurința** în utilizarea claselor personalizate,​ oferind posibilitatea de a efectua **operații** cum ar fi **adunarea**,​ **scăderea** sau **compararea** obiectelor de tipul definit de noi.+În cadrul acestui laborator, am descoperit **importanța supraîncărcării operatorilor** într-o clasă și modul în care acest proces ne permite să efectuăm diverse operații într-un mod **intuitiv**,​ la fel cum procedăm și cu **tipurile de date standard** (**int****float****char**,...). Prin **supraîncărcarea operatorilor**,​ am reușit să **îmbunătățim lizibilitatea și ușurința** în utilizarea claselor personalizate,​ oferind posibilitatea de a efectua **operații** cum ar fi **adunarea**,​ **scăderea** sau **compararea** obiectelor de tipul definit de noi.
  
-Am înțeles, de asemenea, când este necesar să supraîncărcăm un operator ca **funcție membră** a unei clase și când este mai potrivit să îl supraîncărcăm ca **funcție friend**. Operatorii care au nevoie de **acces direct** la membrii clasei, cum ar fi **operatorii unari** sau **operatorul de asignare**, sunt adesea implementați ca **funcții membre**. În schimb, operatorii care implică obiecte de **diferite tipuri** (de exemplu, un obiect al clasei noastre și un tip fundamental precum **int** sau **double**) pot fi implementați mai eficient ca **funcții friend**, pentru a permite accesul din exterior la membri privați **fără** a compromite **încapsularea**.+Am înțeles, de asemenea, când este necesar să **supraîncărcăm** un operator ca **funcție membră** a unei clase și când este mai potrivit să îl supraîncărcăm ca **funcție friend**. Operatorii care au nevoie de **acces direct** la membrii clasei, cum ar fi **operatorii unari** sau **operatorul de asignare**, sunt adesea implementați ca **funcții membre**. În schimb, operatorii care implică obiecte de **diferite tipuri** (de exemplu, un obiect al clasei noastre și un tip fundamental precum **int** sau **double**) pot fi implementați mai eficient ca **funcții friend**, pentru a permite accesul din exterior la membri privați **fără** a compromite **încapsularea ​datelor clasei**.
poo-is-ab/laboratoare/04.1729499406.txt.gz · Last modified: 2024/10/21 11:30 by razvan.cristea0106
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