în C++, supraîncărcarea operatorului este un polimorfism în timp de compilare. Este o idee de a da o semnificație specială unui operator existent în C++ fără a-i schimba sensul inițial.
În acest articol, vom discuta în continuare despre supraîncărcarea operatorilor în C++ cu exemple și vom vedea ce operatori putem sau nu supraîncărca în C++.
Supraîncărcarea operatorului C++
C++ are capacitatea de a oferi operatorilor o semnificație specială pentru un tip de date, această capacitate fiind cunoscută sub numele de supraîncărcare a operatorului. Supraîncărcarea operatorului este un polimorfism în timp de compilare. De exemplu, putem supraîncărca un operator „+” într-o clasă precum String, astfel încât să putem concatena două șiruri de caractere folosind doar +. Alte clase de exemplu în care operatorii aritmetici pot fi supraîncărcați sunt numere complexe, numere fracționale, numere întregi mari etc.
Exemplu:
int a; float b,sum; sum = a + b;>
Aici, variabilele a și b sunt de tipurile int și float, care sunt tipuri de date încorporate. Prin urmare, operatorul de adăugare „+” poate adăuga cu ușurință conținutul lui a și b. Acest lucru se datorează faptului că operatorul de adăugare + este predefinit pentru a adăuga variabile numai de tipul de date încorporat.
Implementare:
rune în powershell
C++
// C++ Program to Demonstrate the> // working/Logic behind Operator> // Overloading> class> A {> >statements;> };> int> main()> {> >A a1, a2, a3;> >a3 = a1 + a2;> >return> 0;> }> |
>
>
În acest exemplu, avem 3 variabile a1, a2 și a3 din clasa de tip A. Aici încercăm să adăugăm două obiecte a1 și a2, care sunt de tip definit de utilizator, adică de tip clasa A folosind operatorul +. Acest lucru nu este permis, deoarece operatorul de adăugare + este predefinit pentru a opera numai pe tipuri de date încorporate. Dar aici, clasa A este un tip definit de utilizator, astfel încât compilatorul generează o eroare. Aici intervine conceptul de supraîncărcare a operatorului.
Acum, dacă utilizatorul dorește să facă operatorul + să adauge două obiecte de clasă, utilizatorul trebuie să redefinească semnificația operatorului + astfel încât să adauge două obiecte de clasă. Acest lucru se realizează prin utilizarea conceptului de supraîncărcare a operatorului. Așadar, ideea principală din spatele supraîncărcării operatorului este utilizarea operatorilor C++ cu variabile de clasă sau obiecte de clasă. Redefinirea semnificației operatorilor într-adevăr nu schimbă sensul lor inițial; în schimb, li s-a dat un sens suplimentar împreună cu cele existente.
Exemplu de supraîncărcare a operatorului în C++
C++
// C++ Program to Demonstrate> // Operator Overloading> #include> using> namespace> std;> class> Complex {> private>:> >int> real, imag;> public>:> >Complex(>int> r = 0,>int> i = 0)> >{> >real = r;> >imag = i;> >}> >// This is automatically called when '+' is used with> >// between two Complex objects> >Complex operator+(Complex>const>& obj)> >{> >Complex res;> >res.real = real + obj.real;> >res.imag = imag + obj.imag;> >return> res;> >}> >void> print() { cout << real <<>' + i'> << imag <<>'
'>; }> };> int> main()> {> >Complex c1(10, 5), c2(2, 4);> >Complex c3 = c1 + c2;> >c3.print();> }> |
>
>Ieșire
12 + i9>
Diferența dintre funcțiile operatorului și funcțiile normale
Funcțiile operatorului sunt aceleași cu funcțiile normale. Singurele diferențe sunt că numele unei funcții de operator este întotdeauna cuvânt cheie operator urmat de simbolul operatorului, iar funcțiile operatorului sunt apelate atunci când este utilizat operatorul corespunzător.
Exemplu
C++
#include> using> namespace> std;> class> Complex {> private>:> >int> real, imag;> public>:> >Complex(>int> r = 0,>int> i = 0)> >{> >real = r;> >imag = i;> >}> >void> print() { cout << real <<>' + i'> << imag << endl; }> >// The global operator function is made friend of this> >// class so that it can access private members> >friend> Complex operator+(Complex>const>& c1,> >Complex>const>& c2);> };> Complex operator+(Complex>const>& c1, Complex>const>& c2)> {> >return> Complex(c1.real + c2.real, c1.imag + c2.imag);> }> int> main()> {> >Complex c1(10, 5), c2(2, 4);> >Complex c3> >= c1> >+ c2;>// An example call to 'operator+'> >c3.print();> >return> 0;> }> |
>
>Ieșire
12 + i9>
Putem supraîncărca toți operatorii?
Aproape toți operatorii pot fi supraîncărcați, cu excepția câtorva. Mai jos este lista operatorilor care nu pot fi supraîncărcați.
sizeof typeid Scope resolution (::) Class member access operators (.(dot), .* (pointer to member operator)) Ternary or conditional (?:)>
Operatori care pot fi supraîncărcați în C++
Putem supraîncărca
convertiți data șirului
Operatori unari Operatori binari Operatori speciali ( [ ], (), etc)
Dar, printre aceștia, există și câțiva operatori care nu pot fi supraîncărcați. Sunt
Operator de rezoluție a domeniului (: operator de selecție de membri Selectarea de membri prin *
Pointer către o variabilă membru
- Operator condiționat (? Sizeof operator sizeof()
| Operatori care pot fi supraîncărcați | Exemple |
|---|---|
| Aritmetică binară | +, -, *, /, % |
| Aritmetică unară | +, -, ++, — |
| Misiune | =, +=,*=, /=,-=, %= |
| Pe bit | &, | , <> , ~ , ^ |
| Dereferențiare | (->) |
| Alocarea dinamică a memoriei, De-alocarea | Nou, șterge |
| Indice | [ ] |
| Apel de funcție | () |
| Logic | &, | |, ! |
| Relațional | >, <, = =, = |
De ce nu pot fi supraîncărcați operatorii menționați mai sus?
1. dimensiunea operatorului
Aceasta returnează dimensiunea obiectului sau tipului de date introdus ca operand. Acesta este evaluat de compilator și nu poate fi evaluat în timpul rulării. Incrementarea corectă a unui pointer într-o matrice de obiecte se bazează implicit pe dimensiunea operatorului. Modificarea sensului său folosind supraîncărcarea ar duce la prăbușirea unei părți fundamentale a limbajului.
2. Typeid Operator
Acest lucru oferă unui program CPP capacitatea de a recupera tipul efectiv derivat al obiectului la care se face referire printr-un pointer sau referință. Pentru acest operator, scopul este de a identifica în mod unic un tip. Dacă vrem să facem ca un tip definit de utilizator „să arate” ca un alt tip, se poate folosi polimorfismul, dar sensul operatorului tipid trebuie să rămână nealterat, altfel ar putea apărea probleme serioase.
3. Rezoluția domeniului (::) Operator
Acest lucru ajută la identificarea și specificarea contextului la care se referă un identificator prin specificarea unui spațiu de nume. Este complet evaluat în timpul execuției și funcționează mai degrabă pe nume decât pe valori. Operanzii rezoluției domeniului sunt expresii de note cu tipuri de date, iar CPP nu are sintaxă pentru captarea lor dacă ar fi supraîncărcat. Deci este imposibil din punct de vedere sintactic să supraîncărcați acest operator.
4. Operatori de acces pentru membrii clasei (.(punc ), .* (indicator către operatorul membru))
Importanța și utilizarea implicită a operatorilor de acces pentru membrii clasei pot fi înțelese prin următorul exemplu:
Exemplu:
C++
// C++ program to demonstrate operator overloading> // using dot operator> #include> using> namespace> std;> class> ComplexNumber {> private>:> >int> real;> >int> imaginary;> public>:> >ComplexNumber(>int> real,>int> imaginary)> >{> >this>->real = real;> >this>->imaginar = imaginar;> >}> >void> print() { cout << real <<>' + i'> << imaginary; }> >ComplexNumber operator+(ComplexNumber c2)> >{> >ComplexNumber c3(0, 0);> >c3.real =>this>->real + c2.real;> >c3.imaginary =>this>->imaginar + c2.imaginar;> >return> c3;> >}> };> int> main()> {> >ComplexNumber c1(3, 5);> >ComplexNumber c2(2, 4);> >ComplexNumber c3 = c1 + c2;> >c3.print();> >return> 0;> }> |
>
>Ieșire
comutați java
5 + i9>
Explicaţie:
Declarația ComplexNumber c3 = c1 + c2; este tradus intern ca ComplexNumber c3 = c1.operator+ (c2); pentru a invoca funcția operator. Argumentul c1 este transmis implicit folosind '.' operator. Următoarea instrucțiune folosește și operatorul punct pentru a accesa funcția membru print și pentru a trece c3 ca argument.
În plus, acești operatori lucrează și pe nume și nu pe valori și nu există nicio prevedere (sintactic) pentru a le supraîncărca.
5. Operator ternar sau condiționat (?:).
Operatorul ternar sau condiționat este o reprezentare scurtă a unei instrucțiuni if-else. În operator, expresiile adevărat/fals sunt evaluate doar pe baza valorii de adevăr a expresiei condiționale.
conditional statement ? expression1 (if statement is TRUE) : expression2 (else)>
O funcție care supraîncărcă operatorul ternar pentru o clasă spune ABC folosind definiția
ABC operator ?: (bool condition, ABC trueExpr, ABC falseExpr);>
nu ar putea garanta că doar una dintre expresii a fost evaluată. Astfel, operatorul ternar nu poate fi supraîncărcat.
Puncte importante despre supraîncărcarea operatorului
1) Pentru ca supraîncărcarea operatorului să funcționeze, cel puțin unul dintre operanzi trebuie să fie un obiect de clasă definit de utilizator.
2) Operator de atribuire: Compilatorul creează automat un operator de atribuire implicit pentru fiecare clasă. Operatorul de atribuire implicit atribuie toți membrii părții drepte în partea stângă și funcționează bine în majoritatea cazurilor (acest comportament este același cu constructorul de copiere). Vezi asta pentru mai multe detalii.
3) Operator de conversie: De asemenea, putem scrie operatori de conversie care pot fi utilizați pentru a converti un tip în alt tip.
Exemplu:
C++
sortare inserare java
// C++ Program to Demonstrate the working> // of conversion operator> #include> using> namespace> std;> class> Fraction {> private>:> >int> num, den;> public>:> >Fraction(>int> n,>int> d)> >{> >num = n;> >den = d;> >}> >// Conversion operator: return float value of fraction> >operator>float>()>const> >{> >return> float>(num) />float>(den);> >}> };> int> main()> {> >Fraction f(2, 5);> >float> val = f;> >cout << val <<>'
'>;> >return> 0;> }> |
>
>Ieșire
0.4>
Operatorii de conversie supraîncărcați trebuie să fie o metodă de membru. Alți operatori pot fi fie metoda membrului, fie metoda globală.
4) Orice constructor care poate fi apelat cu un singur argument funcționează ca un constructor de conversie, ceea ce înseamnă că poate fi folosit și pentru conversia implicită în clasa construită.
Exemplu:
C++
// C++ program to demonstrate can also be used for implicit> // conversion to the class being constructed> #include> using> namespace> std;> class> Point {> private>:> >int> x, y;> public>:> >Point(>int> i = 0,>int> j = 0)> >{> >x = i;> >y = j;> >}> >void> print()> >{> >cout <<>'x = '> << x <<>', y = '> << y <<>'
'>;> >}> };> int> main()> {> >Point t(20, 20);> >t.print();> >t = 30;>// Member x of t becomes 30> >t.print();> >return> 0;> }> |
>
>Ieșire
x = 20, y = 20 x = 30, y = 0>
Test despre supraîncărcarea operatorului