虚函数const与虚函数non-const

vam*_*msi 15 c++

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;
}
Run Code Online (Sandbox Code Playgroud)

为什么输出打印"这是常数基数".但是,如果我删除func()的基本版本中的const,它会打印"这是非常量派生"

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

Naw*_*waz 34

 virtual void func() const  //in Base
 virtual void func()        //in Derived
Run Code Online (Sandbox Code Playgroud)

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

当您删除const部件,然后他们的签名匹配,然后编译器将派生类定义func视为基类函数的重写版本func,因此如果对象的运行时类型是Derived类型,则调用派生类函数.此行为称为运行时多态.

  • 如果人们发现了这个问题,那就在权衡一个老问题.现在用C++ 11记住要将`override`添加到你希望实际覆盖的所有函数中,编译器会告诉你它们何时没有,就像在这种情况下一样. (5认同)
  • @vamsi因为你有一个指向Base*的指针.在Base接口中,只有一个'func'重载可用,而且它是只读的(const).当它是编译器通过基指针看到的唯一一个时,它是只读的这一事实是无关紧要的.如果两个函数都是在Base中定义的,那么编译器自然会选择非const函数.派生的一个甚至无法在此上下文中调用. (3认同)
  • @vamsi,`Base`的定义只包含一个函数,所以这是被调用的函数. (2认同)

sti*_*472 5

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

如果您尝试创建指向成员函数(PTMF)的指针,还可以了解有关此内容的更多信息,但这是非常必要的(但是,对于学习或练习而言可能是一件好事)。

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