为什么纯虚拟析构函数需要实现

时间:2014-01-14 09:00:01

标签: c++ pure-virtual virtual-destructor

我知道需要纯虚拟析构函数的情况。我也知道,如果我们不为它们提供实现,它将给我一个链接器错误。我不明白为什么在代码片段中应该是这种情况,如下所示:

int main()
{
    Base * p = new Derived;
}

这里没有删除,所以没有调用析构函数,因此不需要它的实现(假设它应该像其他正常的函数一样声明但未定义,链接器只在我们调用时才会抱怨)...或者我错过了什么?

我需要理解为什么这应该是一个特例?

根据 BoBTFish

的评论

修改

这是我的Base和Derived类

class Base
{
public:
    Base(){}
    virtual ~Base() = 0;
};

class Derived : public Base
{
};

4 个答案:

答案 0 :(得分:8)

编译器尝试在给定virtual(纯粹的或非纯粹的)析构函数的情况下构建虚拟表,并且它会因为无法找到实现而抱怨。

virtual析构函数与其他virtual函数不同,因为它们在对象被销毁时被调用,无论它是否被实现。这需要编译器将它添加到vf表中,即使它没有被显式调用,因为派生类析构函数需要它。

讽刺的是,标准需要一个纯virtual析构函数才能实现。

答案 1 :(得分:6)

C ++ 11标准:

12.4析构函数

第9段:

析构函数可以声明为虚拟(10.3)或纯虚拟(10.4); 如果该类别的任何对象或任何 派生类是在程序中创建的,析构函数应该被定义。如果一个类有一个带有的基类 虚析构函数,它的析构函数(无论是用户还是隐式声明)都是虚拟的。

答案 2 :(得分:3)

析构函数以这种方式与其他虚函数不同,因为它们是特殊的并且在基础中自动调用,没有可能的,有用的或有意义的方法来阻止它。

  

[C++11: 12.4/9]:析构函数可以声明为virtual(10.3)或纯virtual(10.4); 如果在程序中创建了该类或任何派生类的任何对象,则应定义析构函数。如果一个类有一个带有虚析构函数的基类,那么它的析构函数(无论是用户还是隐式声明)都是虚拟的。

基础总是被破坏,为此,需要一个基础析构函数定义。相反,根本不会自动调用其他重写的虚函数。因此特殊情况要求。

struct Base
{
   virtual ~Base()    = 0;  // invoked no matter what
   virtual void foo() = 0;  // only invoked if `Base::foo()` is called
};

Base::~Base() {}
/* void Base::foo() {} */

struct Derived : Base
{
   virtual void foo() { /* Base::foo(); */ }
};

int main()
{
    std::unique_ptr<Base> ptr(new Derived());
}

答案 3 :(得分:0)

一个实际的原因是,在几乎所有实现中,析构函数都在vtable的虚拟成员函数列表中排在首位。并且实现倾向于在定义第一个虚拟成员函数时定义vtable本身。因此,没有析构函数,没有vtable。而vtable至关重要。