类内部的纯虚析构函数定义会导致编译错误

Pure virtual destructor definition inside class gives compilation error

本文关键字:编译 错误 定义 析构函数 内部      更新时间:2023-10-16

pure virtual destructor in基类应该有定义。否则,编译器将在链接期间从派生类析构函数生成对基类析构函数的调用,并将导致链接错误。

我尝试在基类内部像下面这样定义纯虚析构函数:
class base
{
   public:
      base()
      {
         cout << "constructor in base classn";
      }
      virtual ~base()=0
      {}
};

编译错误:

错误:function-definition上的pure-specifier

然后我尝试在基类之外定义函数,如下所示:
class base
{
   public:
      base()
      {
         cout << "constructor in base classn";
      }
      virtual ~base()=0;
};
base::~base()
{
}

这将删除编译错误,并且它的行为与我的理解一致。

但是我的问题是如何在基类之外定义纯虚析构函数来消除编译错误?

你的第二个例子是正确的

许多其他的答案都假设使用默认实现的纯虚函数是非法的,然而这是不正确的。

对于纯虚析构函数,必须有一个定义(参见xmoex answer中的链接)。

§10.4/2函数声明不能同时提供纯说明符和一个定义

但是,正如您注意到的,可以在声明之外提供定义

我看了这一页:

http://www.gotw.ca/gotw/031.htm

和根据我的理解,纯虚析构函数必须有一个定义(即使是空的),因为每个派生类都必须调用基类析构函数

这样写的语法无效:

virtual ~base()=0
{}

如果你想提供纯虚成员函数的实现,你应该在类之外实现。大多数情况下不应该这样做,因为无论如何都不应该调用纯虚函数。然而,可以定义纯虚函数的实现。

实际上,纯虚析构函数必须有实现。这是因为在对象析构时调用所有基类的析构函数,而不管给定类中的析构函数是否为纯虚函数。

因此,如果您创建了从base派生的任何类的实例,那么在某个时刻,该对象所属的所有类的析构函数将被调用,包括base::~base()析构函数。如果你没有定义它,链接器将找不到所需的符号,并会报错。

析构函数是唯一的方法,即使它是纯虚函数,也必须有一个实现才能使它所定义的类有用。因此,与@Kiril的回答相反,我想说纯虚函数可以有实现。

有点跑题:

struct base {
    virtual void func() = 0;
};
void base::func() { /* default implementation */ }
class derived : public base{
    void func() { base::func(); } // have to explicitly call default implementation.
};

纯虚方法可以有实现,但它们使基类抽象,并强制派生类覆盖这些方法。

假设在基类中有一个指针成员。你想在析构函数中删除它,但又想使类抽象——所以你实现了纯虚析构函数。

这是一个实现细节——析构函数的实现不应该从外部可见。