为什么纯虚拟析构函数需要实现
Why a pure virtual destructor needs an implementation
我知道需要纯虚拟析构函数的情况。我也知道,如果我们不为它们提供实现,它会给我一个链接器错误。我不明白的是为什么在代码片段中会出现这种情况,如下所示:
int main()
{
Base * p = new Derived;
}
这里没有删除,所以没有调用析构函数,所以不需要它的实现(假设它的行为应该像其他已声明但未定义的正常函数一样,链接器仅在我们调用它们时才抱怨)......还是我错过了什么?
我需要了解为什么这应该是一个特例?
编辑:基于BoBTFish的评论
这是我的基类和派生类
class Base
{
public:
Base(){}
virtual ~Base() = 0;
};
class Derived : public Base
{
};
编译器尝试在给定virtual
(纯或非纯)析构函数的情况下构建虚拟表,并且由于找不到实现而抱怨。
virtual
析构函数与其他virtual
函数不同,因为它们是在销毁对象时调用的,无论它是否已实现。这要求编译器将其添加到 vf 表中,即使它未显式调用,因为派生类析构函数需要它。
从学究上讲,该标准要求实现纯virtual
析构函数。
C++11 标准:
12.4 析构函数
第9段:
析构函数可以声明为虚拟 (10.3) 或纯虚拟 (10.4);如果该类的任何对象或任何派生类是在程序中创建的,应定义析构函数。如果类具有具有虚拟析构函数,其析构函数(无论是用户声明还是隐式声明)是虚拟的。
构函数在这一点上与其他虚函数不同,因为它们是特殊的,并且在基中自动调用,没有可能、有用或有意义的方法来防止它。
碱基
[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());
}
一个实际的原因是析构函数在几乎所有实现的 vtable 中的虚拟成员函数列表中都排在第一位。实现倾向于在定义第一个虚拟成员函数时定义 vtable 本身。所以,没有析构函数,没有vtable。而 vtable 至关重要。
- 如何在 CRTP 中实现析构函数?
- 如何使用指针向量实现类析构函数 C++.
- 使用shared_ptr时需要实现析构函数、复制构造函数、赋值运算符
- 当声明了虚拟析构函数但没有实现时会发生什么情况
- 如何实现在构造函数中使用自身的对象的析构函数
- 如何实现纯虚拟析构函数
- C++ 链接列表队列实现和析构函数错误:"Aborted (Core Dumped)"
- 为什么纯虚拟析构函数需要实现
- GoogleMock让我在mock类中实现析构函数吗
- 根据析构函数和移动构造函数实现移动赋值
- 重写默认构造函数/析构函数而不实现它们
- G++ 警告,缺少纯虚拟析构函数的实现
- C++ 抽象类是否应该为(虚拟)析构函数提供实现
- 静态字段的析构函数.辛格尔顿实现
- 当在头文件上而不是在CPP文件上实现时,析构函数会导致内存泄漏——仅在linux上实现
- 生产编译器如何在流控制上实现析构函数处理
- 为什么我们没有义务实现纯虚析构函数
- 单链表-由于析构函数实现导致的分段错误
- 使用D_ptr实现析构函数
- 实现析构函数