Während ich mit der Implementierung eines virtuellen Zuweisungsoperators spielte, endete ich mit einem lustigen Verhalten. Es ist kein Compilerfehler, da g ++ 4.1, 4.3 und VS 2005 das gleiche Verhalten haben.Warum verhält sich die virtuelle Zuweisung anders als andere virtuelle Funktionen derselben Signatur?
Grundsätzlich verhält sich der virtuelle Operator = anders als jede andere virtuelle Funktion in Bezug auf den Code, der tatsächlich ausgeführt wird.
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 &)
}
Der Effekt ist, dass der virtuelle Operator = ein anderes Verhalten als jede andere virtuelle Funktion mit der gleichen Signatur hat ([0] im Vergleich zu [1]), die durch die Basisversion des Betreibers aufrufen, wenn sie aufgerufen durch reale abgeleitete Objekte ([1]) oder abgeleitete Referenzen ([3]), während sie als reguläre virtuelle Funktion ausgeführt werden, wenn sie durch Basisreferenzen ([2]) aufgerufen werden, oder wenn der lvalue oder rvalue Basisreferenzen und die anderen a sind Abgeleitete Referenz ([4], [5]).
Gibt es eine vernünftige Erklärung für dieses seltsame Verhalten?
keine Es gibt hier beteiligt zu erraten. Die Regeln sind sehr streng. – MSalters
Danke, Die wirkliche Antwort (wie von bereits drei Leuten geschrieben) ist, dass der Compiler generated = Operator für die abgeleitete Klasse implizit den Base :: operator = aufruft. Ich markiere dies als "akzeptierte Antwort", da es die erste war. –
'a = static_cast (b);' wäre eine Möglichkeit, C-Style-Casts zu vermeiden (die das Risiko einer versehentlichen Neuinterpretierung beinhalten). –