简体   繁体   English

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

[英]Why a pure virtual destructor needs an implementation

I know the cases where pure virtual destructors are needed.我知道需要纯虚拟析构函数的情况。 I also know that If we don't provide an implementation for them it will give me a linker error.我也知道如果我们不为他们提供实现,它会给我一个链接器错误。 What I don't understand is why this should be the case in a code fragment as shown below:我不明白的是为什么在代码片段中应该是这种情况,如下所示:

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

Here there is no delete, so no call to destructor and so no need for its implementation(assuming it is supposed to behave like other normal functions which are declared but not defined, linker complains only when we call them)...or am I missing something?这里没有删除,所以没有调用析构函数,所以不需要它的实现(假设它应该像其他声明但未定义的普通函数一样,链接器只有在我们调用它们时才会抱怨)......或者我是遗漏了什么?

I need to understand why this should be a special case?我需要明白为什么这应该是一个特例?

Edit: based on comments from BoBTFish编辑:基于BoBTFish 的评论

Here are my Base and Derived classes这是我的基础类和派生类

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

class Derived : public Base
{
};

The compiler tries to build the virtual table given a virtual (pure or not) destructor, and it complains because it can't find the implementation.编译器尝试在给定virtual (纯或非)析构函数的情况下构建虚拟表,并且由于找不到实现而抱怨。

virtual destructors differ from other virtual functions because they are called when the object is destroyed, regardless of whether it was implemented or not. virtual析构函数不同于其他virtual函数,因为它们在对象被销毁时被调用,无论它是否被实现。 This requires the compiler to add it to the vf table, even if it's not called explicitly, because the derived class destructor needs it.这需要编译器将它添加到 vf 表中,即使它没有被显式调用,因为派生类析构函数需要它。

Pedantically, the standard requires a pure virtual destructor to be implemented.迂腐地,该标准需要实现一个纯virtual析构函数。

C++11 standard: C++11 标准:

12.4 Destructors 12.4 析构函数

Paragraph 9:第 9 段:

A destructor can be declared virtual (10.3) or pure virtual (10.4); 析构函数可以声明为虚拟(10.3)或纯虚拟(10.4); if any objects of that class or any derived class are created in the program, the destructor shall be defined. 如果在程序中创建了该类或任何派生类的任何对象,则应定义析构函数。 If a class has a base class with a virtual destructor, its destructor (whether user- or implicitly-declared) is virtual. 如果一个类有一个带有虚拟析构函数的基类,它的析构函数(无论是用户声明的还是隐式声明的)是虚拟的。

Destructors differ from other virtual functions in this way, because they are special and automatically invoked in bases, with no possible, useful or meaningful way to prevent it.析构函数在这一点上不同于其他虚函数,因为它们是特殊的并且在基类中自动调用,没有可能、有用或有意义的方法来阻止它。

[C++11: 12.4/9] : A destructor can be declared virtual (10.3) or pure virtual (10.4); [C++11: 12.4/9] : 析构函数可以声明为virtual (10.3) 或纯virtual (10.4); if any objects of that class or any derived class are created in the program, the destructor shall be defined .如果在程序中创建了该类或任何派生类的任何对象,则应定义析构函数 If a class has a base class with a virtual destructor, its destructor (whether user- or implicitly-declared) is virtual.如果一个类有一个带有虚拟析构函数的基类,它的析构函数(无论是用户声明的还是隐式声明的)是虚拟的。

Bases are always destroyed, and to do this, a base destructor definition is required.基类总是被销毁,为此,需要一个基类析构函数定义。 Conversely, other overridden virtual functions are not invoked automatically at all.相反,其他覆盖的虚函数根本不会自动调用。 Hence the special-case requirement.因此,特殊情况要求。

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());
}

One practical reason is that destructors come first in the list of virtual member functions in the vtable in practically all implementations.一个实际的原因是,在几乎所有实现中,析构函数在 vtable 中的虚拟成员函数列表中排在第一位。 And implementations tend to define the vtable itself when it defines the first virtual member function.并且实现倾向于在定义第一个虚拟成员函数时定义 vtable 本身。 So, no destructor, no vtable.所以,没有析构函数,没有 vtable。 And the vtable is critical.并且 vtable 很关键。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM