考虑这样的三个类:
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
,其指针指向A
,B
指针指针相同。
删除Foo
的实例时,删除指针a
,然后调用b
的析构函数,但~B
尝试访问a
},在~Foo
中被释放,导致分段错误。
在运行b
的主体之前,有没有办法调用~Foo
的析构函数?
我知道我可以通过使b
指针或使a
成为非指针来解决这个问题。如果A
是抽象的,后者不起作用,我想知道是否可以在不使b
指针的情况下进行。
PS:A
和B
都来自图书馆,因此我无法更改其实施。
答案 0 :(得分:7)
遵循RAII原则。
将Foo::a
更改为std::unique_ptr<A>
。从delete
。
~Foo
现在会在~Foo
结束后和b.~Bar()
之后销毁。
请注意,成员按声明顺序创建,并以相反的顺序销毁。 (令人惊讶的是,初始化列表中的顺序不会改变创建顺序)。因此,如果您希望a
比b
更长,只需先声明它。
答案 1 :(得分:1)
创建一个中间类。
class PreFoo
{
A* a:
...
};
class Foo : public PreFoo
{
B b;
...
};
答案 2 :(得分:-2)
编辑:纠正错误(感谢@Yakk)
您需要在B
中设置Foo
指针,以便您可以控制析构函数中的删除顺序或使A
成为非指针并将其放在{{1}之前在B
的成员顺序中,它在Foo
之后被销毁,但这会使代码变脆,因为成员声明的顺序现在很重要。在您的代码中对此进行评论。