删除派生对象时是否始终会调用基础析构函数?

jma*_*erx 2 c++

说我有以下内容:

class Foo {
public:
void destroy();
~Foo()
{
   destroy();
}
};

class Bar : public Foo {
public:
~Bar() {}
};
Run Code Online (Sandbox Code Playgroud)

如果我有一个Bar对象,当对象栏被删除时,是否会调用Foo的析构函数?

谢谢

Oli*_*rth 16

是.

但上面的代码很危险; 如果你没有声明~Foo()virtual,那么~Bar()如果通过一个对象调用delete一个Bar对象,则不会被调用Foo *.

  • 从技术上讲,它是UB,但这是最常见的失败方法.+1无论如何. (2认同)
  • 另一种选择是保护基类析构函数.这意味着你不能在其上调用delete,但是当你不需要v-table时就避免使用v-table.有时候你会想要一个基类继承或非多态的原因,例如向用户公开一个较小的接口,甚至将const-reference绑定到它. (2认同)

Jar*_*Par 5

是的,如果您持有Bar参考,这将有效.然而,这是一个非常脆弱的解决方案,因为它不相反(持有Foo&Foo*指向a Bar).为了使这个工作,Foo析构函数必须是虚拟的.否则它将执行非虚拟分派并仅调用析构函数Foo.

class Foo { 
public: 
void destroy(); 
virtual ~Foo() 
{ 
   destroy(); 
} 
}; 

class Bar : public Foo { 
public: 
virtual ~Bar() {} 
}; 
Run Code Online (Sandbox Code Playgroud)

在预期继承的一般情况下,涉及的类型应使用虚拟析构函数进行标记.像大多数规则一样,尽管100%的情况并非如此.但是,我鼓励您阅读以下文章中的问题#2(感谢Steve的链接),而不是深入了解所有案例.