Contenuti del Corso
OOP in C++
OOP in C++
Sovraccarico degli Operatori
L'overloading degli operatori è una funzionalità avanzata nei linguaggi di programmazione orientati agli oggetti che consente di ridefinire il comportamento degli operatori per le classes
definite dall'utente. Sovraccaricando gli operatori, è possibile fornire implementazioni personalizzate per le operazioni che coinvolgono oggetti della propria class
, rendendo il codice più intuitivo ed espressivo.
Sintassi dell'overloading degli operatori
L'overloading si ottiene definendo funzioni membro speciali o funzioni amiche che implementano il comportamento desiderato per l'operatore. La sintassi per sovraccaricare gli operatori varia a seconda dell'operatore che si desidera sovraccaricare. La sintassi generale è la seguente:
overloading.h
return_type operator operator_symbol(parameters);
La sintassi, o più precisamente, il numero di parametri e il tipo di ritorno, dipende anche dal fatto che si stiano sovraccaricando operatori come funzioni membro o come funzioni amiche.
Member.h
Friend.h
class Example { public: Example operator+ (const Example& other) { // Define behavior for operator+ } };
Tabella degli operatori che possono essere sovraccaricati
Ecco una tabella che elenca tutti gli operatori che possono essere sovraccaricati. Tuttavia, è importante notare che, sebbene sia possibile sovraccaricare questi operatori, non è assolutamente necessario sovraccaricarli tutti per le proprie classes
.
Sovraccarico degli operatori di inserimento stream
Per sovraccaricare gli operatori <<
e >>
per una class
, si definisce tipicamente una funzione friend o una funzione membro che prende uno stream di output (std::ostream&
) o uno stream di input (std::istream&
) come operando sinistro e un oggetto della propria class
come operando destro. Questa funzione quindi formatta i dati dell'oggetto e li invia verso o dal flusso.
Point.h
class Point { public: friend std::ostream& operator<<(std::ostream& out, const Point& point); friend std::istream& operator>>(std::istream& in, Point& point); private: int x, y; }; std::ostream& operator<<(std::ostream& out, const Point& point) { return out << "x: " << point.x << ", y: " << point.y << std::endl; } std::istream& operator>>(std::istream& in, Point& point) { return in >> point.x >> point.y; }
Il sovraccarico degli operatori di inserimento stream, come <<
, consente di definire un comportamento di output personalizzato per gli oggetti delle proprie classes
quando vengono inviati a uno stream di output come std::cout
. Questa funzionalità è particolarmente utile per migliorare la leggibilità e l'usabilità del codice quando si lavora con tipi di dati personalizzati.
Il sovraccarico dell'operatore <<
per il flusso di output è più comune rispetto al sovraccarico dell'operatore >>
per il flusso di input, poiché le operazioni di input con >>
possono essere più soggette a errori.
Sovraccarico degli operatori aritmetici
È possibile sovraccaricare altri operatori aritmetici (-
, *
, /
, %
) in modo simile per eseguire operazioni personalizzate con i tipi definiti dall'utente.
main.cpp
#include <iostream> class Point { public: Point(int xCoord, int yCoord) : x(xCoord), y(yCoord) {} Point operator+(const Point& other) { return Point(x + other.x, y + other.y); } int getX() { return x; } int getY() { return y; } private: int x, y; }; int main() { Point p = Point(2, 4) + Point(2, 6); std::cout << p.getX() << ' ' << p.getY() << std::endl; }
L'operatore è sovraccaricato come funzione membro della Point
class
. Prende un altro oggetto Point
come parametro e restituisce un nuovo oggetto Point
che rappresenta la somma dei due punti. L'operatore +
può essere sostituito con -
, *
, /
o %
, con i relativi aggiustamenti alla logica di implementazione.
Incremento e Decremento
Sia gli operatori di incremento e decremento prefisso e postfisso (++
e --
) possono essere sovraccaricati per classes
personalizzate. Iniziamo con la versione prefissa:
main.cpp
#include <iostream> class Point { public: Point(int xCoord, int yCoord) : x(xCoord), y(yCoord) {} // Prefix increment operator (++point) Point& operator++() { ++x; ++y; return *this; } int getX() { return x; } int getY() { return y; } private: int x, y; }; int main() { Point p(2, 2); ++p; std::cout << p.getX() << ' ' << p.getY() << std::endl; }
L'operatore di decremento viene sovraccaricato in modo simile all'operatore di incremento, utilizzando l'operatore --
e l'operazione di sottrazione.
Come puoi vedere, il sovraccarico degli operatori di incremento e decremento prefissi è diretto. Tuttavia, la situazione si complica con le versioni postfisse. Ricorda che esiste una differenza nell'ordine di esecuzione tra le operazioni prefisse e postfisse.
Quando si sovraccaricano gli operatori di incremento e decremento postfissi, è necessario implementare anche la caratteristica dell'ordine di esecuzione. Apparirà in questo modo:
main.cpp
#include <iostream> class Point { public: Point(int xCoord, int yCoord) : x(xCoord), y(yCoord) {} // Postfix increment operator (point++) Point operator++(int) { Point temp = *this; // Creating a temp variable ++(this->x); // Incrementing original Point's x ++(this->y); // Incrementing original Point's y return temp; // Returning created temp variable } int getX() { return x; } int getY() { return y; } private: int x, y; }; int main() { Point p(2, 2); p++; std::cout << p.getX() << ' ' << p.getY() << std::endl; }
Il parametro intero viene passato senza nome solo per segnalare al compilatore che si sta sovraccaricando l'operatore di incremento postfisso. Questo è necessario perché le dichiarazioni degli operatori prefisso e postfisso sono altrimenti identiche.
Nell'implementazione dell'operatore di incremento postfisso, il valore originale dell'oggetto viene memorizzato in una variabile temporanea (temp
). L'oggetto corrente viene quindi incrementato, ma l'operatore restituisce il valore memorizzato in temp
. Questo significa che la variabile viene incrementata, ma la modifica ha effetto solo nell'espressione successiva, poiché l'operatore restituisce il valore originale.
Grazie per i tuoi commenti!