in C++, l'overload degli operatori è un polimorfismo in fase di compilazione. Si tratta di dare un significato speciale a un operatore esistente in C++ senza cambiarne il significato originale.
In questo articolo discuteremo ulteriormente dell'overload degli operatori in C++ con esempi e vedremo quali operatori possiamo o non possiamo sovraccaricare in C++.
Sovraccarico degli operatori C++
Il C++ ha la capacità di fornire agli operatori un significato speciale per un tipo di dati, questa capacità è nota come sovraccarico degli operatori. L'overload degli operatori è un polimorfismo in fase di compilazione. Ad esempio, possiamo sovraccaricare un operatore '+' in una classe come String in modo da poter concatenare due stringhe utilizzando semplicemente +. Altre classi di esempio in cui gli operatori aritmetici possono essere sovraccaricati sono i numeri complessi, i numeri frazionari, i grandi numeri interi, ecc.
Esempio:
int a; float b,sum; sum = a + b;>
Qui, le variabili a e b sono di tipo int e float, che sono tipi di dati incorporati. Quindi l’operatore di addizione “+” può facilmente aggiungere il contenuto di a e b. Questo perché l'operatore di addizione + è predefinito per aggiungere solo variabili del tipo di dati integrato.
Implementazione:
C++
esegui in PowerShell
// C++ Program to Demonstrate the> // working/Logic behind Operator> // Overloading> class> A {> >statements;> };> int> main()> {> >A a1, a2, a3;> >a3 = a1 + a2;> >return> 0;> }> |
>
>
In questo esempio, abbiamo 3 variabili a1, a2 e a3 di tipo classe A. Qui stiamo provando ad aggiungere due oggetti a1 e a2, che sono di tipo definito dall'utente cioè di tipo classe A utilizzando l'operatore +. Ciò non è consentito perché l'operatore di addizione + è predefinito per funzionare solo su tipi di dati incorporati. Ma in questo caso la classe A è un tipo definito dall'utente, quindi il compilatore genera un errore. È qui che entra in gioco il concetto di sovraccarico dell'operatore.
Ora, se l'utente desidera che l'operatore + aggiunga due oggetti di classe, deve ridefinire il significato dell'operatore + in modo tale che aggiunga due oggetti di classe. Questo viene fatto utilizzando il concetto di sovraccarico dell'operatore. Quindi l'idea principale alla base dell'overload degli operatori è utilizzare gli operatori C++ con variabili di classe o oggetti di classe. Ridefinire il significato degli operatori in realtà non cambia il loro significato originale; invece, è stato loro dato un significato aggiuntivo insieme a quelli già esistenti.
Esempio di sovraccarico degli operatori in 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();> }> |
>
convertire la data della stringa
>Produzione
12 + i9>
Differenza tra funzioni operatore e funzioni normali
Le funzioni dell'operatore sono le stesse delle funzioni normali. Le uniche differenze sono che il nome di una funzione operatore è sempre the parola chiave dell'operatore seguito dal simbolo dell'operatore e le funzioni dell'operatore vengono chiamate quando viene utilizzato l'operatore corrispondente.
Esempio
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;> }> |
>
execvp
>Produzione
12 + i9>
Possiamo sovraccaricare tutti gli operatori?
Quasi tutti gli operatori possono essere sovraccaricati, tranne alcuni. Di seguito è riportato l'elenco degli operatori che non possono essere sovraccaricati.
sizeof typeid Scope resolution (::) Class member access operators (.(dot), .* (pointer to member operator)) Ternary or conditional (?:)>
Operatori che possono essere sottoposti a sovraccarico in C++
Possiamo sovraccaricare
Operatori unari Operatori binari Operatori speciali ( [ ], (), ecc.)
Ma tra questi ci sono alcuni operatori che non possono essere sovraccaricati. Sono
Operatore di risoluzione dell'ambito (: Operatore di selezione dei membri Selezione dei membri tramite *
Puntatore a una variabile membro
- Operatore condizionale (? Operatore Sizeof sizeof()
| Operatori che possono essere sovraccaricati | Esempi |
|---|---|
| Aritmetica binaria | +, -, *, /, % |
| Aritmetica unaria | +, -, ++, — |
| Incarico | =, +=,*=, /=,-=, %= |
| Bit per bit | &, | , <> , ~ , ^ |
| Dereferenziazione | (->) |
| Allocazione dinamica della memoria, De-allocazione | Nuovo, elimina |
| Pedice | [] |
| Chiamata di funzione | () |
| Logico | &, | |, ! |
| Relazionale | >, <, = =, = |
Perché gli operatori sopra indicati non possono essere sovraccaricati?
1. sizeof Operator
Restituisce la dimensione dell'oggetto o del tipo di dati immesso come operando. Questo viene valutato dal compilatore e non può essere valutato durante il runtime. Il corretto incremento di un puntatore in un array di oggetti si basa implicitamente sull'operatore sizeof. Alterarne il significato tramite il sovraccarico causerebbe il collasso di una parte fondamentale del linguaggio.
2. Operatore typeid
Ciò fornisce a un programma CPP la capacità di recuperare il tipo effettivamente derivato dell'oggetto a cui fa riferimento un puntatore o un riferimento. Per questo operatore, il punto è identificare in modo univoco un tipo. Se vogliamo far sì che un tipo definito dall'utente 'assomigli' a un altro tipo, è possibile utilizzare il polimorfismo ma il significato dell'operatore typeid deve rimanere inalterato, altrimenti potrebbero sorgere seri problemi.
3. Risoluzione dell'ambito (::) Operatore
Ciò aiuta a identificare e specificare il contesto a cui fa riferimento un identificatore specificando uno spazio dei nomi. Viene completamente valutato in fase di esecuzione e funziona sui nomi anziché sui valori. Gli operandi della risoluzione dell'ambito sono espressioni di note con tipi di dati e CPP non ha sintassi per catturarli se fosse sovraccarico. Quindi è sintatticamente impossibile sovraccaricare questo operatore.
4. Operatori di accesso dei membri della classe (.(punto ), .* (puntatore all'operatore membro))
L'importanza e l'uso implicito degli operatori di accesso ai membri della classe possono essere compresi attraverso il seguente esempio:
Esempio:
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>->reale = reale;> >this>->immaginario = immaginario;> >}> >void> print() { cout << real <<>' + i'> << imaginary; }> >ComplexNumber operator+(ComplexNumber c2)> >{> >ComplexNumber c3(0, 0);> >c3.real =>this>->reale + c2.reale;> >c3.imaginary =>this>->immaginario + c2.immaginario;> >return> c3;> >}> };> int> main()> {> >ComplexNumber c1(3, 5);> >ComplexNumber c2(2, 4);> >ComplexNumber c3 = c1 + c2;> >c3.print();> >return> 0;> }> |
>
>Produzione
5 + i9>
Spiegazione:
L'affermazione NumeroComplesso c3 = c1 + c2; è tradotto internamente come NumeroComplesso c3 = c1.operator+ (c2); per richiamare la funzione operator. L'argomento c1 viene passato implicitamente utilizzando il metodo '.' operatore. Anche l'istruzione successiva utilizza l'operatore punto per accedere alla funzione membro print e passare c3 come argomento.
Inoltre, questi operatori lavorano anche sui nomi e non sui valori e non è previsto (sintatticamente) il loro sovraccarico.
5. Operatore ternario o condizionale (?:).
L'operatore ternario o condizionale è una rappresentazione abbreviata di un'istruzione if-else. Nell'operatore le espressioni vero/falso vengono valutate solo in base al valore di verità dell'espressione condizionale.
conditional statement ? expression1 (if statement is TRUE) : expression2 (else)>
Una funzione che sovraccarica l'operatore ternario per una classe dice ABC usando la definizione
ABC operator ?: (bool condition, ABC trueExpr, ABC falseExpr);>
non sarebbe in grado di garantire che solo una delle espressioni sia stata valutata. Pertanto, l'operatore ternario non può essere sovraccaricato.
Punti importanti sul sovraccarico dell'operatore
1) Affinché l'overloading degli operatori funzioni, almeno uno degli operandi deve essere un oggetto di classe definito dall'utente.
stringa Java con formato
2) Operatore di Assegnazione: Il compilatore crea automaticamente un operatore di assegnazione predefinito con ogni classe. L'operatore di assegnazione predefinito assegna tutti i membri del lato destro al lato sinistro e funziona correttamente nella maggior parte dei casi (questo comportamento è lo stesso del costruttore di copia). Vedi questo per maggiori dettagli.
3) Operatore di conversione: Possiamo anche scrivere operatori di conversione che possono essere utilizzati per convertire un tipo in un altro tipo.
Esempio:
C++
// 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;> }> |
>
>Produzione
coda di priorità Java
0.4>
Gli operatori di conversione sovraccaricati devono essere un metodo membro. Altri operatori possono essere il metodo membro o il metodo globale.
4) Qualsiasi costruttore che può essere chiamato con un singolo argomento funziona come costruttore di conversione, il che significa che può essere utilizzato anche per la conversione implicita nella classe da costruire.
Esempio:
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;> }> |
>
>Produzione
x = 20, y = 20 x = 30, y = 0>
Quiz sul sovraccarico degli operatori