EC++: cosa fa operator=

Appunti tratti dalla rilettura di Effective C++ di Scott Meyers. Terzo blocco: Costruttori, distruttori e operatori di assegnamento.

(16) In operator= vanno assegnati tutti i membri dati nella classe.

Se non si scrive esplicitamente l'operatore assegnamento per una classe, viene generato per noi. Purtroppo non é possibile lasciare che il C++ faccia il lavoro di default e occuparsi di gestire solo i membri che vogliamo vengano gestiti in modo diverso dal default. Se si scrive un operator=, questo si deve occupare dell'assegnamento di tutti i membri dato della classe.

Occorre prestare particolare attenzione a questa regola quando si modifica una classe aggiungendo un nuovo data-member e quando si crea una classe derivata.

Vediamo il caso di una semplice gerarchia di classi:

#include <iostream>
using namespace std;

class Base {
public:
Base(int x = 0) : _x(x) {
}
protected:
int _x;
};

class Derived : public Base {
public:
Derived(int x) : Base(x), _y(x) {
}

Derived & operator=(const Derived& rhs);

private:
int _y;
};

Date queste definizioni, sembrerebbe ragionevole definire l'operatore assegnamento per la classe Derived in questo modo:

Derived& Derived::operator=(const Derived& rhs) {
if (this == &rhs)
return *this;

_y = rhs._y;
return *this;
}

Ma sarebbe un errore, dato che questo porta ad aggiornare solo il dato membro relativo alla classe derivata, trascurando il membro della classe base. Occorre infatti esplicitamente chiamare l'operatore assegnamento per la classe base:

Derived& Derived::operator=(const Derived& rhs) {
if (this == &rhs)
return *this;

Base::operator=(rhs);
_y = rhs._y;
return *this;
}

La stessa cautela va tenuta nell'implementazione del copy-ctor. Se si scrive il costruttore-copia per la classe derivata, bisogna fare attenzione a chiamare il costruttore per la classe base, anche se questo non é definito esplicitamente:

Derived(const Derived& rhs) : Base(rhs), _y(rhs._y) {}

Altrimenti si cadrebbe nello stesso problema visto sopra, e il nuovo oggetto sarebbe inizializzato, nelle sue componenti relative alla classe di base, con i valori di default e non con la copia delle componenti dell'oggetto passato.

Nessun commento:

Posta un commento