C++纯虚函数是否可以有函数体?

71

纯虚函数(当我们设置= 0)也可以有一个函数体。

如果根本不会调用纯虚函数,为什么要为其提供函数体呢?


抱歉!我在这个论坛上的术语还有些陌生。我已经接受了我认为正确的答案。感谢您的建议。 - Vijay
3个回答

104

您对于不能调用纯虚函数的假设是完全不正确的。当一个函数被声明为纯虚函数时,它只意味着这个函数无法通过虚拟派发机制动态调用,但是这个同样的函数可以轻松地通过非虚拟的、直接的方式进行静态调用(即不通过虚拟派发)。

在C++语言中,当调用中使用了函数的限定名称时,即调用中指定的函数名具有“<类名>::<函数名>”的形式时,将执行虚函数的非虚拟调用。

例如:

struct S 
{
  virtual void foo() = 0;
};

void S::foo() 
{
  // body for pure virtual function `S::foo`
}

struct D : S 
{
  void foo() 
  {
    S::foo();       
    // Non-virtual call to `S::foo` from derived class

    this->S::foo(); 
    // Alternative syntax to perform the same non-virtual call 
    // to `S::foo` from derived class
  }
};

int main() 
{
  D d;

  d.S::foo(); 
  // Another non-virtual call to `S::foo`
}

30
"Effective C++" Meyers提到了一个纯虚函数需要有实现体的原因:派生类可以在其代码中调用实现体。如果两个不同的派生类的代码的一部分相似,则将其上移至层次结构中是有意义的,即使该函数应该是纯虚函数也是如此。
请参见这里

糟糕...我有《Effective C++》的第12版,但我错过了那个声明。我认为定义它的一个原因是因为它可能会被调用,并且默认抛出异常,这可能不是您在软件中想要的结果...(当然,重复使用代码也是一个很好的理由)。 - Alexis Wilke
链接已经失效。 - Jimmy T.

8

对于大多数纯虚函数,您是正确的。然而,对于纯虚析构函数,定义相应的析构函数实现非常重要:

  • "纯虚"是为了要求派生类实现它们的析构函数。
  • 您的基类析构函数实现是为了使派生类析构函数能够成功地“链接”在后面。

13
我发现这个答案已经有一年了,但是我刚看到一个链接引导人们来到这个问题,所以......你的第一个观点是错误的,纯虚析构函数并不会强制派生类实现析构函数。即使它隐式定义,派生类也总会有一个析构函数。使用纯虚析构函数的一个优点是,如果一个类没有其他适合成为纯虚函数的函数,则可以将其设置为抽象类。 - Jonathan Wakely

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接