请考虑以下代码段:
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?
}
答案 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级的做法也是如此。
通过传递这些信息,您可以让其他人清楚地看到您的代码所做的事情,而无需他们不得不寻找信息。