【问题标题】:Default destructor in subclasses of base class with a virtual destructor具有虚拟析构函数的基类子类中的默认析构函数
【发布时间】:2018-06-29 14:10:51
【问题描述】:

我有一个带有虚拟析构函数的基类AA 的后代 BC 使用默认析构函数。通过指向A的指针删除C的对象是否安全?

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

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的析构函数,最后是A的析构函数?

【问题讨论】:

    标签: c++ virtual-destructor


    【解决方案1】:

    是的,它是安全的。在派生类的析构函数中添加virtual 是多余的。

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

    在您的情况下,它发现动态类型是C,因此调用了C::~CC::~C 自动连接到 B::~B,而那个自动连接到 A::~A

    要求C(或B)的析构函数为virtual 是没有意义的。毕竟,如果A::~Avirtual,那么运行时无论如何都必须找出动态的C 类型。此时,C::~C 是否为virtual 并不重要。会有什么不同?

    【讨论】:

    • 通过该描述,不明显的是,如果您将指针声明为“中间”类型 B,并且实际的具体运行时类型是 C,它也可以正常工作。AFAIK,派生类不能“去虚拟化”基类中虚拟的东西。
    【解决方案2】:

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

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

    发件人:

    15.4 析构函数 [class.dtor]

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

    由于A 有一个虚拟析构函数,那么BCD 分别有一个虚拟析构函数并且:

    delete aptr;
    

    工作正常。

    【讨论】:

      【解决方案3】:

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

      是的。由于A 的析构函数是virtualC 的析构函数将被调用。这仅仅是由于 动态调度 的工作原理。

      【讨论】:

        猜你喜欢
        • 2021-08-22
        • 2012-06-26
        • 2010-10-24
        • 2017-04-21
        • 2019-04-20
        • 2011-11-16
        • 2011-03-21
        • 2012-12-24
        • 2013-11-01
        相关资源
        最近更新 更多