Overloading di operatori

L’overloading di un operatore consiste nella ridefinizione del funzionamento di un operatore esistente. L’overload di un operatore è possibile a patto che i parametri dell’operatore siano diversi dalla definizione standard.

Non si possono ridefinire operatori di tipi primitivi, come gli int, char, float, ecc.

Questa caratteristica ci consente di definire degli operatori per le classi scritte da noi nel nostro progetto, in modo da scrivere codice compatto e pulito.

Se ad esempio abbiamo una classe Warrior, che rappresenta un guerriero di un gioco, il quale ha un membro di tipo int che contiene un ID univoco, potremmo voler avere un operatore che ci consenta di sapere se due variabili di tipo Warrior siano effettivamente lo stesso warrior, ovvero entrambe abbiano lo stesso ID.

Se facessimo qualcosa di questo tipo :

Warrior w1;

w1.ID = 10;

Warrior w2;

w2.ID = 10;

return (w1 == w2) ;

otterremmo un false come ritorno, perchè l’implementazione di default dell’operatore == non prevede il confronto che ci aspettiamo e che ci serve. Chiaramente potremmo fare direttamente:

return(w1.ID == w2.ID)

ma ci sono decine di motivazioni per spiegare i vantaggi di scrivere questo controllo in un posto solo, tra cui i vantaggi dell’incapsulamento, della riusabilità, della manutenibilità, il debugging, e tanti altri.

Detto questo, vediamo come ridefinire l’operatore ==:

bool Warrior::operator==(const Warrior &other) const {

… return this->ID == other->ID;

}

L’operatore di uguaglianza da come output un valore booleano vero o falso, per cui come valore di ritorno della funzione di overload useremo un bool. Warrior:: sta ad indicare che l’operatore è sovraccaricato nella classe che ci interessa (e lo scriveremo quindi nel file .cpp della nostra classe Warrior).  La keywork “operator” indica che stiamo appunto effettuando l’overload di un operatore, e il simbolo == indica quale operatore stiamo ridefinendo.

Come parametro di ingresso, l’operatore == vuole un riferimento costante a un tipo, e visto che dobbiamo comparare due Warrior, indicheremo come parametro un “const Warrior &other”, ovvero un riferimento a un oggetto di tipo Warrior, ma costante. Viene passato un riferimento costante per due motivi: 1) il riferimento implicitamente si traduce in un passaggio di un puntatore, che è molto più efficiente rispetto a un passaggio per valore 2) il fatto che sia costante è garanzia del fatto che all’interno dell’operatore l’oggetto da comparare non venga modificato.

A ulteriore indicazione che il metodo non modificherà nessun dato, è aggiunta la keyword const anche al corpo del metodo, che impedisce appunto la modifica di dati al suo interno.

La logica dell’operatore è banale, basta ritornare infatti un semplice confronto tra i membri ID dei nostri Warrior, dove this è un puntatore all’oggetto su cui è chiamato l’operatore, mentre other è l’oggetto di confronto. In pratica, se facciamo

a==b

stiamo chiamando l ‘operatore == sull’oggetto a, il che significa che sarà chiamata l’implementazione dell’operatore == definita per quel tipo, dove this è a, e il parametro passato alla funzione è il riferimento a b

quindi, avendo ridefinito l’operatore == per il nostro Warrior, rieseguendo il codice:

return w1 == w2; 

dove w1 e w2 sono due oggetti di tipo Warrior, verrà richiamata la funzione definita da noi nella nostra classe Warrior, che eseguirà il confronto tra gli ID.

Allo stesso modo possiamo effettuare l’overload di un operatore a livello globale, ovvero non dentro una classe ma in una funzione globale, in questo modo:

si può ridefinire un operatore a livello globale:
bool operator ==(const Warrior& w1, const Warrior& w2)
{
return w1->ID == w2->ID;
}

la differenza rispetto all’overload nella nostra classe è che l’operatore, essendo globale, non ha nessun puntatore implicito a se stesso, ovvero nessun “this”. Ha bisogno per cui che gli passiamo sia il primo che il secondo oggetto da confrontare.

Annunci
  1. Lascia un commento

Rispondi

Inserisci i tuoi dati qui sotto o clicca su un'icona per effettuare l'accesso:

Logo WordPress.com

Stai commentando usando il tuo account WordPress.com. Chiudi sessione / Modifica )

Foto Twitter

Stai commentando usando il tuo account Twitter. Chiudi sessione / Modifica )

Foto di Facebook

Stai commentando usando il tuo account Facebook. Chiudi sessione / Modifica )

Google+ photo

Stai commentando usando il tuo account Google+. Chiudi sessione / Modifica )

Connessione a %s...

%d blogger hanno fatto clic su Mi Piace per questo: