En jouant avec l'implémentation d'un opérateur d'assignation virtuelle, j'ai terminé avec un comportement amusant. Ce n'est pas un problème de compilateur, puisque g ++ 4.1, 4.3 et VS 2005 partagent le même comportement. Fondamentalement, l'opérateur virtuel = se comporte différemment de toute autre fonction virtuelle par rapport au code qui est en cours d'exécution.Pourquoi l'affectation virtuelle se comporte-t-elle différemment des autres fonctions virtuelles de la même signature?
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'effet est que l'opérateur virtuel = a un comportement différent de toute autre fonction virtuelle avec la même signature ([0] par rapport à [1]), en appelant la version de base de l'opérateur lorsqu'il est appelé par real Derived objects ([1]) ou Derived references ([3]) alors qu'il fonctionne comme une fonction virtuelle régulière lorsqu'il est appelé via les références de base ([2]), ou lorsque lvalue ou rvalue sont des références de base et l'autre un Référence dérivée ([4], [5]).
Y at-il une explication raisonnable à ce comportement étrange?
Il n'y a pas de deviner en cause ici. Les règles sont très strictes. – MSalters
Merci, La vraie réponse (telle que publiée par déjà trois personnes) est que le compilateur généré opérateur = pour la classe Derived appelle implicitement l'opérateur Base :: operator =. Je marque ceci comme «réponse acceptée» comme c'était le premier. –
'a = static_cast (b);' serait un moyen d'éviter les lancers de type C (qui risquent de faire accidentellement une réinterprétation) –