【问题标题】:overloading virtual operator -> ()重载虚拟运算符 -> ()
【发布时间】:2011-09-08 14:42:27
【问题描述】:

这只是一个实验代码。

struct B
{
  virtual B* operator -> () { return this; }
  void foo () {} // edit: intentionally NOT virtual
};

struct D : B
{
  virtual D* operator -> () { return this; }
  void foo () {}
};

int main ()
{
  B &pB = *new D;
  pB->foo();  // calls B::foo() !
}

我知道operator 必须使用对象或引用来调用;因此,在上述情况下,引用 pB 是否仍然坚决支持 B 的对象? 虽然这不实用,但出于好奇,有没有办法通过pB 调用D::operator ->

【问题讨论】:

  • 当你想拥有 foo() 虚拟时,拥有 operator-> 虚拟是没有意义的。
  • 我可能在这里遗漏了一些东西,但是将void foo() 设为虚拟有什么问题? operator->() 在这种情况下完全没有意义,尤其是因为它只返回 this
  • @In silico,我同意,这只是一个实验代码,用于了解当 operator -> 变为 virtual 时会发生什么。我已经编辑了我的问题。谢谢。

标签: c++ operator-overloading virtual overriding


【解决方案1】:

我认为它正在调用D::operator->,但返回值被视为B*,因此正在调用B::foo()

这是协变返回类型行为方式的产物。

【讨论】:

    【解决方案2】:

    它调用哪个运算符(在这种情况下可能是D::operator->)并不重要,重要的是this。在这种情况下,this 指针的类型为B*,因此foo 调用被取消引用到B::foo。如果是virtual - 它会正常工作,但你故意没有做到virtual...

    【讨论】:

      【解决方案3】:

      pB 的类型为 B&。因此,在其上调用的任何方法(例如operator->)都将获得B 中的签名,因此pB.operator->() 将返回B*。当然,因为是虚拟的,所以使用D中的实际实现。重要的是返回类型是由 pB 变量的类型定义的。

      所以,我们的operator-> 返回了一个B*,因此调用foo() 的过程与任何其他B* 一样。

      【讨论】:

      • 这个答案并不新鲜,但我认为尝试进一步扩展逻辑可能会有用。
      【解决方案4】:

      根据调用中使用的对象的动态类型调用虚拟成员函数。非虚成员函数根据调用中使用的对象的static类型进行调用。

      函数foo 不是虚拟的。这意味着它总是按照对象的 static 类型调用。本例中的静态类型为B(因为B::operator ->的结果声明类型为B *),所以调用B::foo

      【讨论】:

        猜你喜欢
        • 2021-11-12
        • 2019-10-21
        • 2020-09-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-08-08
        • 1970-01-01
        相关资源
        最近更新 更多