【问题标题】:virtual function const vs virtual function non-const虚函数 const 与虚函数非常量
【发布时间】:2012-02-28 19:11:12
【问题描述】:
class Base
{
   public:
   virtual void func() const
   {
     cout<<"This is constant base "<<endl;
   }
};

class Derived : public Base
{
   public:
   virtual void func()
   {
     cout<<"This is non constant derived "<<endl;
   }
};


int main()
{
  Base *d = new Derived();
  d->func();
  delete d;

  return 0;
}

为什么输出打印“This is constant base”。但是,如果我在 func() 的基本版本中删除 const,它会打印“This is non constant derived”

d->func() 应该正确调用 Derived 版本,即使 Base func() 是 const 对吗?

【问题讨论】:

标签: c++


【解决方案1】:
 virtual void func() const  //in Base
 virtual void func()        //in Derived

const 部分实际上是函数签名的一部分,这意味着派生类定义了一个 函数而不是覆盖基类函数。这是因为他们的签名不匹配。

当您删除const 部分时,它们的签名匹配,然后编译器将func 的派生类定义视为基类函数func覆盖版本,因此如果对象的运行时类型为Derived 类型,则调用派生类函数。这种行为称为运行时多态性。

【讨论】:

  • 我在这里很困惑。如果两者都被视为 2 个不同的函数,为什么 d->func() 调用派生版本,因为这里没有适用的 const。
  • 对。事实上,一个类定义两个相同的函数是很常见的,一个是const,一个不是。
  • @vamsi,Base的定义只包含一个函数,所以就是那个函数。
  • @vamsi 因为你有一个指向 Base* 的指针。在 Base 接口中,只有一个 'func' 重载可用,即只读 (const)。当它是编译器通过基指针看到的唯一一个时,它是只读的这一事实是无关紧要的。如果这两个函数都在 Base 中定义,那么编译器自然会选择非常量函数。在这种情况下,派生的甚至无法调用。
  • 权衡一个老问题,以防人们发现这个。现在使用 C++11,请记住将 override 添加到您希望实际覆盖的所有函数中,编译器会在它们没有覆盖时告诉您,就像在这种情况下一样。
【解决方案2】:

virtual void func() 实际上与virtual void func() const 的签名不同。因此,您没有覆盖原始的只读基本函数。你最终在 Derived 中创建了一个新的虚函数。

如果您曾经尝试创建指向成员函数 (PTMF) 的指针,您也可以了解更多相关信息,但这是一种极少的必要性(但可能对学习或实践有好处)。

C++11 中的 override 关键字在帮助避免此类错误方面特别方便。然后编译器会告诉您,您在派生中对 'func' 的定义不会覆盖任何内容。

【讨论】:

    【解决方案3】:

    不,因为virtual void func() 不是virtual void func() const 的覆盖。

    【讨论】:

      猜你喜欢
      • 2012-02-06
      • 2015-04-20
      • 2015-09-17
      • 2011-09-16
      • 2021-07-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多