在玩实现虚拟赋值运算符时,我以一个有趣的行为结束。这不是编译器故障,因为 g++ 4.1、4.3 和 VS 2005 具有相同的行为。
基本上,就实际执行的代码而言,virtual operator= 的行为与任何其他虚函数不同。
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 &)
}
效果是虚拟运算符 = 具有与具有相同签名的任何其他虚拟函数不同的行为([0] 与 [1] 相比),通过在通过真实派生对象调用时调用运算符的基本版本([1] ) 或派生引用 ([3]),而当通过基引用 ([2]) 调用时,或者当左值或右值是基引用而另一个是派生引用 ([4], [5])。
这种奇怪的行为有什么合理的解释吗?