派生类中是否需要显式声明析构函数?

时间:2014-02-13 22:24:56

标签: c++ virtual destructor

请考虑以下代码段:

class A
{
virtual void function();
public:
  virtual ~A() {};
}

class B: public A
{
virtual void function() override final;
public:
  /*virtual*/ ~B() {}; // does this d-tor have to be declared at all?
}

我可以轻松找到有关基类析构函数的信息,例如http://en.cppreference.com/w/cpp/language/destructor

  

“通过指向base的指针删除对象会调用未定义的行为   除非基类中的析构函数是虚拟的。普通的   准则是基类的析构函数必须是公共的   和虚拟或受保护和非虚拟“

基类中的虚拟析构函数是必须的,派生类的析构函数如何,是否必​​须显式声明/定义?我发现它很混乱,因为派生类的析构函数也是自动虚拟的。在vtable寻址方面跳过派生类的析构函数的声明/定义是否合法?以下情况如何:

class A
{
virtual void function();
public:
  virtual ~A() {};
}

class B: public A
{
virtual void function() override;
public:
  /*virtual*/ ~B() {}; // does this d-tor have to be declared at all?
}

class C: public B
{
virtual void function() override final;
public:
  /*virtual*/ ~C() {};  // does this d-tor have to be declared at all?
}

3 个答案:

答案 0 :(得分:5)

无需在派生类中明确定义析构函数。根据C ++标准

  

如果一个类有一个带有虚析构函数的基类,那么它的析构函数   (无论是用户还是隐式声明)是虚拟

如果您对访问控制感到烦恼,那么

  

隐式声明的析构函数是其内联的 public 成员   类。

编译器会将其隐式定义的析构函数的地址放在vtable中。因此派生类的vtable将存储派生类的析构函数的地址。

为了您的代码的可读性,您可以编写例如

class B: public A
{
virtual void function() override final;
public:
  virtual ~B() = default;
}

答案 1 :(得分:3)

不,不需要申报;从具有声明为virtual的给定函数的类继承的类不需要将其继承的表单声明为virtual,因为它为virtual。这包括隐式声明的析构函数。

答案 2 :(得分:0)

正如其他人所说,不,你不需要在后代类中声明一个do-nothing析构函数,因为它从祖先类中继承下来。

但是,请记住,您的C类可能来自某些第三方库B类,例如VendorBAwesomeness.dll,而B又可能来自Microsoft在mswonderful.dll中的A类。

如果你想对班级的读者和用户感到高兴,你应该考虑在你的C类中指定virtual,因为你在阅读它时在B类的界面中看到它,并且作者当他/她了解A级时,B级的做法也是如此。

通过传递这些信息,您可以让其他人清楚地看到您的代码所做的事情,而无需他们不得不寻找信息。