虚类的析构函数究竟做什么

What do destructors for virtual classes do exactly?

本文关键字:什么 究竟 析构函数      更新时间:2023-10-16

假设我们有这些类。

class A 
{
public:
   void doSomething() = 0;
   A();
   virtual ~A();
private:
   vector<SomeStuff> cont;
   bool yesNo;
}
class B: public A
{
public:
   B();
   ~B();
private:
   bool Byesno;
}

所以首先调用A的构造函数,然后再调用B的构造函数,当我们析构B时,首先调用B的析构函数,然后再调用A的析构函数。基本上,A的析构函数将删除B和的继承变量,B的析构函数将删除特定于类的变量。我说的对吗?

我不明白的是,如果我们甚至不能实例化A类型的对象,我们怎么能调用A的析构函数?它是如何在内部工作的?

B是A等等。将调用A的析构函数以确保清除B的A部分。您的类不使用virtual关键字,所以我不确定您为什么对虚析构函数感到疑惑,但是既然您在疑惑,这可能会有所帮助:

class A
{
   public:
       virtual ~A() { cout << "A::~A()" << endl; }
};
class B : public A
{
   public:
       ~B() { cout << "B::~B()" << endl; }
};
int main()
{
    A* obj = new B();
    delete obj;
    return 0;
}

您期望的输出将是

B::~B()
A::~A()

但是,如果没有将A的析构函数声明为virtual,则输出将简单地为

A::~A()
因此,总而言之,如果您的代码涉及到多态性,并且您希望调用指向对象的析构函数而不是指针类型本身的析构函数,则必须将基类的析构函数声明为virtual。

每个析构函数运行三个阶段:

    用户代码
  1. 将类成员的销毁委托给相应的析构函数
  2. 将基类的销毁委托给相应的析构函数

基本类型的析构函数通常是微不足道的,即什么都不做。从技术上讲,你可以认为

B::~B() { Byesno = false; }

B::~B()
{
    Byesno = false;  // explicit
    Byesno.~bool();  // implicit, member
    A::~A();         // implicit, base class
}

A::~A()
{
    yesNo.~bool();   // implicit, member
    cont.~vector();  // implicit, member
}

~bool()为空,并且将被内联,因此您可以看到的唯一调用是对~vector()的调用。

所有这些都是叫做d'tor的另一件事。如果A的d'tor是非虚拟的,B的d'tor只有在被销毁的对象已知是B对象时才会被调用:

A a;
B b;
A *ap = new B;
delete ap;

~A()用于a对象(正确),~B()用于b对象(也正确),~A()用于ap指向的对象(不正确,但我们不知道更好)。如果~A()是虚的,则d'tor调用本身将在v'表中查找,v'表中包含一个指向~B()的指针。