具有虚析构函数的基类的子类中的默认析构函数

时间:2018-01-20 12:43:29

标签: c++ virtual-destructor

我有一个带有虚拟析构函数的基类methodA具有使用默认析构函数的后代AB。通过指向C

的指针删除C对象是否安全?

更具体地说,请考虑以下示例代码:

A

要运行的代码如下所示:

class A {
 public:
      A(){};
      virtual ~A() {/* code here */};
 };
 class B: public A {
      B() {/* code....*/};
      /* NO DESTRUCTOR SPECIFIED */
   };
 class C: public B {/*same as above, no destructor */};
 class D: public B {/* same as above, no destructor*/}

A* getAPointer(void); /* a function returning a C or a D*/ A* aptr=getAPointer(); /* aptr is declared as A*, but points to either an object of class C or class D*/ delete aptr; 安全吗?它是否做得对:如果delete aptr指向类aptr的对象,C首先调用aptr的析构函数,然后C析构函数,最后是B的析构函数?

3 个答案:

答案 0 :(得分:4)

  

通过指向A?

的指针删除C对象是否安全?

是的,它完全安全,因为BCD类中的所有析构函数都将隐式虚拟。

自:

  

15.4析构函数[class.dtor]

     

10析构函数可以声明为虚拟(13.3)或纯虚拟(13.4);   如果在该类中创建了该类或任何派生类的任何对象   程序,应该定义析构函数。 如果某个类有基类   使用虚拟析构函数,它的析构函数(无论是用户还是   隐式声明的是虚拟的。

由于A有一个虚拟析构函数,然后BCD分别具有虚拟析构函数,并且:

delete aptr;

正常工作。

答案 1 :(得分:2)

是的,这很安全。将virtual添加到派生类的析构函数中是多余的。

考虑该机制的工作原理。使用delete时,运行时需要知道销毁链应该从哪个析构函数开始。如果delete操作数的静态类型具有virtual析构函数,那么运行时已经足以知道它必须承担额外的麻烦并检查动态类型。

在您的情况下,它会发现动态类型为C,因此调用C::~CC::~C会自动转到B::~B,而且会自动转到A::~A

要求C(或B' s)析构函数为virtual是没有意义的。毕竟,如果CA::~A,运行时必须找出动态virtual类型。此时,它并不关心C::~C是否virtual。它会有什么不同?

答案 2 :(得分:0)

  

通过指向listId的指针删除C的对象是否安全?

是。由于A的析构函数是 virtual ,因此将调用A的析构函数。这仅仅是由于动态调度的工作原理。