更具体一点:
class B;
class A
{
public:
A(B &b) : _b(b) { }
~A() { _b.do_something(); }
private:
B &_b;
};
class B
{
public:
B() { }
/** other methods */
~B()
{
for (std::list<A*>::iterator it = _bees.begin(); it != _bees.end(); ++it) {
delete *it;
}
}
void do_something();
private:
std::list<A*> _bees;
};
这样做可以吗?
答案 0 :(得分:2)
您引用b
中的A::~A ()
而不是_b
,这将无法编译。假设你的意思是_b
,那么回答是 - 这取决于。它取决于B
引用的类A
对象的生命周期。如果在调用B
类的析构函数之前销毁了类A
的对象,那么它就不行了,否则就可以了。在任何一种情况下,这个代码都不是非常简单的证据,许多人会考虑重新设计以降低其危险性。
如果没有强有力的保证B
在A
被销毁时仍然存在,那么你需要做一些重新设计。例如,您可以按值存储B
(复制它),或使用引用计数或其他“智能”指针。
答案 1 :(得分:2)
是的,假设_b仍然有效(您通过引用使用它)。您可以致电_b
的成员,只要他们不会抛出异常!从析构函数中抛出异常是不好的(tm)。
答案 2 :(得分:1)
语言水平安全。但是,在设计层面,这应该总是让你问“为什么我需要在垂死的物体内进行任务?”。
例如,如果析构函数是由错误启动的清理序列的一个步骤,并且do_something()方法失败,那么这可能会变坏。现在你有两个错误,一个是破坏另一个的恢复。
答案 3 :(得分:1)
对于您发布的代码,可以。
但要注意功能B::do_something
的性质和效果。此功能不应该是虚拟的。它不应该抛出(如前所述),此函数的其他效果不应该破坏正在执行的进程。例如。考虑一下:
~B()
{
for (std::list<A*>::iterator it = _bees.begin(); it != _bees.end(); ++it) {
delete *it; /* this->do_something() implicitly called here must not
invalidate iterator it */
}
}