当派生类的析构函数是非虚拟的时,为什么基类析构函数在派生对象上调用?

时间:2012-10-17 05:31:45

标签: c++ polymorphism virtual-destructor

为什么在下面的示例中调用所有析构函数~D()~C()~B()~A()

只有一个虚拟析构函数:A

以下是代码:

#include<iostream>
using namespace std;

class A
{
public:
  virtual ~A()
  {
    cout<<"destruct A\n";
  }

};
class B:public A
{
public:
  ~B()
  {
  cout<<"destruct B\n"; 
  }
};
class C:public B
{
public:
  ~C()
  {
    cout<<"destruct C\n";
  }
};
class D:public C
{
public:
   ~D()
   {
     cout<<"destruct D\n"; 
   }
};

int main()
{
    A* ptr = new D();
    delete ptr;
    return 0;
}

3 个答案:

答案 0 :(得分:7)

一旦A的析构函数被声明为virtual,所有派生类的析构函数也都是virtual,即使它们没有明确声明为这样。所以行为你看到的正是预期的

答案 1 :(得分:7)

  

派生对象中的销毁顺序完全相反   构造顺序:首先是最衍生的析构函数   调用类,然后调用基类的析构函数。

     

析构函数可以定义为虚拟或甚至纯虚拟。你会   如果你期望派生类是一个虚拟析构函数   通过指向基类的指针销毁。这将确保这一点   将调用派生程度最高的类的析构函数:

A* b1 = new B;//if A has a virtual destructor
delete b1;//invokes B's destructor and then A's

A* b1 = new B;//if A has no virtual destructor
    delete b1;//invokes A's destructor ONLY
  

如果A没有虚拟析构函数,则通过指针删除b1   类型A只会调用A的析构函数。强制执行   在这种情况下,B的析构函数我们必须将A的析构函数指定为   虚拟:

virtual ~A();

REFERENCE

答案 2 :(得分:0)

正如@juanchopanza所说 - 声明基础析构函数虚拟意味着所有后代都有虚拟析构函数。这种继承的虚拟性对于任何方法都是相同的,而不仅仅是析构函数。

这就是为什么我采访了那些不知道关键字做了什么的人,因为他们只需要覆盖从框架派生的方法,所以他们都是虚拟的(叹气)。