Mentre giocavo con l'implementazione di un operatore di assegnamento virtuale, mi sono concluso con un comportamento divertente. Non è un errore del compilatore, dal momento che g ++ 4.1, 4.3 e VS 2005 condividono lo stesso comportamento.Perché l'assegnazione virtuale si comporta in modo diverso rispetto ad altre funzioni virtuali della stessa firma?
In sostanza, l'operatore virtuale = si comporta in modo diverso rispetto a qualsiasi altra funzione virtuale rispetto al codice che viene effettivamente eseguito.
struct Base {
virtual Base& f(Base const &) {
std::cout << "Base::f(Base const &)" << std::endl;
return *this;
}
virtual Base& operator=(Base const &) {
std::cout << "Base::operator=(Base const &)" << std::endl;
return *this;
}
};
struct Derived : public Base {
virtual Base& f(Base const &) {
std::cout << "Derived::f(Base const &)" << std::endl;
return *this;
}
virtual Base& operator=(Base const &) {
std::cout << "Derived::operator=(Base const &)" << std::endl;
return *this;
}
};
int main() {
Derived a, b;
a.f(b); // [0] outputs: Derived::f(Base const &) (expected result)
a = b; // [1] outputs: Base::operator=(Base const &)
Base & ba = a;
Base & bb = b;
ba = bb; // [2] outputs: Derived::operator=(Base const &)
Derived & da = a;
Derived & db = b;
da = db; // [3] outputs: Base::operator=(Base const &)
ba = da; // [4] outputs: Derived::operator=(Base const &)
da = ba; // [5] outputs: Derived::operator=(Base const &)
}
L'effetto è che l'operatore virtuale = ha un comportamento diverso da qualsiasi altra funzione virtuale con la stessa firma ([0] rispetto a [1]), chiamando la versione base dell'operatore quando chiamate tramite oggetti derivati reali ([1]) o riferimenti derivati ([3]) mentre si comporta come una normale funzione virtuale quando chiamata attraverso i riferimenti Base ([2]), o quando il lvalue o il valore di riferimento sono riferimenti Base e l'altro a Riferimento derivato ([4], [5]).
C'è qualche spiegazione ragionevole a questo strano comportamento?
Non c'è indovinare coinvolti qui. Le regole sono molto severe. – MSalters
Grazie, la risposta reale (come postata da tre persone) è che il compilatore ha generato l'operatore = per la classe Derivata chiama implicitamente Base :: operator =. La segnalo come "risposta accettata" come se fosse la prima. –
'a = static_cast (b);' sarebbe un modo per evitare i cast in stile C (che comportano il rischio di fare un cast reinterpretato) –