为什么虚拟分配的行为与同一签名的其他虚拟功能不同? [英] Why does virtual assignment behave differently than other virtual functions of the same signature?

查看:150
本文介绍了为什么虚拟分配的行为与同一签名的其他虚拟功能不同?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在玩实现虚拟赋值运算符的过程中,我以一种有趣的行为结束了。它不是编译器故障,因为g ++ 4.1,4.3和VS 2005共享相同的行为。

While playing with implementing a virtual assignment operator I have ended with a funny behavior. It is not a compiler glitch, since g++ 4.1, 4.3 and VS 2005 share the same behavior.

基本上,虚拟运算符=的行为与任何其他虚拟函数的行为不同到实际执行的代码。

Basically, the virtual operator= behaves differently than any other virtual function with respect to the code that is actually being executed.

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]),当它通过Base引用([2])调用时,或者当左值或右值是Base引用而另一个是Derived引用时,它确实作为常规虚函数执行([3]) ],[5])。

The effect is that the virtual operator= has a different behavior than any other virtual function with the same signature ([0] compared to [1]), by calling the Base version of the operator when called through real Derived objects ([1]) or Derived references ([3]) while it does perform as a regular virtual function when called through Base references ([2]), or when either the lvalue or rvalue are Base references and the other a Derived reference ([4],[5]).

对这种奇怪的行为有什么明智的解释吗?

Is there any sensible explanation to this odd behavior?

推荐答案

这是怎么回事:

如果我将[1]更改为

a = *((Base*)&b);

然后事情就像你期望的那样。在 Derived 中有一个自动生成的赋值运算符,如下所示:

then things work the way you expect. There's an automatically generated assignment operator in Derived that looks like this:

Derived& operator=(Derived const & that) {
    Base::operator=(that);
    // rewrite all Derived members by using their assignment operator, for example
    foo = that.foo;
    bar = that.bar;
    return *this;
}

在您的示例中,编译器有足够的信息来猜测 a b 的类型为 Derived ,因此他们选择使用自动生成的运算符以上就叫你的。这就是你得到的[1]。我的指针强制转换强制编译器按照你的方式执行,因为我告诉编译器忘记 b 类型为派生所以它使用 Base

In your example compilers have enough info to guess that a and b are of type Derived and so they choose to use the automatically generated operator above that calls yours. That's how you got [1]. My pointer casting forces compilers to do it your way, because I tell compiler to "forget" that b is of type Derived and so it uses Base.

其他结果可以用同样的方式解释。

Other results can be explained the same way.

这篇关于为什么虚拟分配的行为与同一签名的其他虚拟功能不同?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆