【问题标题】:(c++) subclass chain destruction when calling destructor(c++) 调用析构函数时子类链销毁
【发布时间】:2016-11-10 09:32:35
【问题描述】:
class A { 
....
};

class B: public A {
int x;
...
};

class C: public A{
A * ptr;
.....
};

class D : public A {
A* ptr1;
A* ptr2;
....
};

注意:我为 B、C、D 制作了所有构造函数,只是没有将它们包含在其中。 所以 A(没有字段)是超类,我有 3 个子类(B、C 和 D),每个子类都有不同的字段。

A 是一个抽象类,它的主要链接是 Class (B,C,D)

所以我可能会遇到类似的情况

B *x = new B {5};
B *x2 = new B {5}
D * y = new D{x,x2);

所以当我做delete y; 时,我想让它链式破坏它的两个字段(B 对象)的 2 个指针。我将如何为 D 类创建析构函数,然后进行链式析构?

就像我展示的示例非常简单,但其他示例的层次越来越多。我想确保所有内容都被删除,以免发生内存泄漏。

我的 D 班 dtor 应该是这个样子吗?

~D(){
delete ptr1;
delete ptr2;
}

对于 C 类的情况,我会这样做吗?

~C(){
    delete ptr;
    }

因为我这样做了但它不起作用我得到内存泄漏所以有什么问题?

【问题讨论】:

  • 你声明你的析构函数是虚拟的吗?
  • 对于 A 类没有。我想如果我在子类@Falmarri 中制作它们,我可以覆盖
  • 是否应该让 A 类析构函数成为纯虚拟的,我真的不需要对 B 类进行析构,它可以使用它的默认值吗?
  • 标准说如果你通过base指针删除(指向derived object),base类应该有virtual析构函数,如果在@987654331中没关系@你正在做一些有用的事情。
  • 我点错了答案,this 是您要找的:

标签: c++ subclass destructor superclass


【解决方案1】:

我认为您的问题是错误的,因为您说这是一个继承链,但在撰写本文时,B、C 和 D 直接从 A 继承。

当您执行new D 时,会发生一个由A、B、C 和D 组成的复合对象 - 它们是按继承顺序构造的。

*y = {
    // B starts
    int x;
    // C starts
    A * ptr;
    // D starts
    A * ptr1;
    A * ptr2;
};

注意析构函数会以相反的顺序被调用,D首先然后C等等,以相反的顺序清理内存(处理对超类的依赖)。但是,这取决于您要删除的对象类型。

如果我们这样做:

D * y = new D;
A * x = y;
delete x;

我们有效地将y 视为A 对象,这意味着我们仅限于A 对象知道的内容,并且只要我们使用x 就可以做到。如果我们使用x 删除,我们将调用~A() 而不是~D()。这就是为什么在这种情况下析构函数需要是虚拟的,这允许virtual ~A() 调用~D(),这将最终再次调用~A()(真正的不是虚拟调度)。

无论您是否使用多态性/向上转换,您的直觉都是正确的 - ~D() 应该只清理 D 对象引入 到类的内存(ptr1 和ptr2),同样适用于~C()(仅限ptr)。

泄漏可能是由于对象切片发生在某处。例如(如果你强制它编译),这比上面的例子更糟糕,因为对象数据不会被复制(相反结构定义相对于被引用的对象类型是不完整的):

D d;
C * c = d; // not too bad, we can't refer to D-specific things.
C c2 = d; // bad, c2 is copied from D up to C superclass and no further.

要非常小心,只将指针/引用传递给可能需要保存派生类型的对象,并且确保在其中使用虚拟析构函数。否则你所做的是正确的,让每个类的析构函数只为那个类清理。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-01-02
    • 1970-01-01
    • 1970-01-01
    • 2018-05-02
    • 2018-02-07
    • 1970-01-01
    • 1970-01-01
    • 2011-05-24
    相关资源
    最近更新 更多