在指针成员之前调用非指针成员的析构函数

时间:2015-09-09 16:00:06

标签: c++ pointers destructor

考虑这样的三个类:

class A {
    int bar;
};

class B {
    A* a;
public:
    B(*A na)
    : a(na)
    {}

    ~B() {
        a->bar = 0;
    }
};

class Foo {
    A* a;
    B b;
public:
    Foo()
    : a(new A)
    , b(a)
    {}

    ~Foo() {
        delete a;
    }
};

创建Foo的实例,会产生一个Foo,其指针指向AB指针指针相同。

删除Foo的实例时,删除指针a,然后调用b的析构函数,但~B尝试访问a },在~Foo中被释放,导致分段错误。

在运行b的主体之前,有没有办法调用~Foo的析构函数?

我知道我可以通过使b指针或使a成为非指针来解决这个问题。如果A是抽象的,后者不起作用,我想知道是否可以在不使b指针的情况下进行。

PS:AB都来自图书馆,因此我无法更改其实施。

3 个答案:

答案 0 :(得分:7)

遵循RAII原则。

Foo::a更改为std::unique_ptr<A>。从delete

中删除~Foo

现在会在~Foo结束后和b.~Bar()之后销毁。

请注意,成员按声明顺序创建,并以相反的顺序销毁。 (令人惊讶的是,初始化列表中的顺序不会改变创建顺序)。因此,如果您希望ab更长,只需先声明它。

答案 1 :(得分:1)

创建一个中间类。

 class PreFoo 
 {
   A* a:
    ...
 };

 class Foo : public PreFoo
 {
   B b;
   ...
 };

答案 2 :(得分:-2)

编辑:纠正错误(感谢@Yakk)

您需要在B中设置Foo指针,以便您可以控制析构函数中的删除顺序或使A成为非指针并将其放在{{1}之前在B的成员顺序中,它在Foo之后被销毁,但这会使代码变脆,因为成员声明的顺序现在很重要。在您的代码中对此进行评论。