我在处理派生类中的构造函数异常时遇到一些问题。当派生类构造函数抛出错误,但父类已经分配了一些对象时。父类的析构函数会被调用吗?
示例:
class A
{
A() { /* Allocate some stuff */ };
virtual ~A() { /* Deallocate stuff */ };
};
class B : public A
{
B()
{
/* Do some allocations */
...
/* Something bad happened here */
if (somethingBadHappened)
{
/* Deallocate B Stuff */
...
/* Throws the error */
throw Error; /* Will A destructor be called? I know B destructor won't */
};
};
~B() { /* Deallocate B Stuff */ };
}
我想知道执行以下操作是否是个好主意:
B()
{
/* Do some allocations */
...
/* Something bad happened here */
if (somethingBadHappened)
{
/* Deallocate B Stuff */
this->~B();
/* Throws the error */
throw Error; /* Will A destructor be called? I know B destructor won't */
};
};
如果没有,做这些事情的正确方法是什么?
最佳答案
异常将导致堆栈展开到正确捕获异常的位置。这意味着抛出异常之前在范围内创建的任何对象都将被破坏,包括本例中的基类对象。
试试这个:
#include <iostream>
class A
{
public:
A() { std::cout << "A::A()\n";}
~A() {std::cout << "A::~A()\n";}
};
class B : public A
{
public:
B()
{
std::cout << "B::B()\n";
throw 'c';
}
// note: a popular point of confusion --
// in this example, this object's destructor
// WILL NOT BE CALLED!
~B()
{
std::cout << "B::~B()\n";
}
};
int main()
{
try
{
B b;
}
catch(...)
{
std::cout << "Fin\n";
}
return 0;
}
输出应为:(注意 B::~B()
未调用)
A::A()
B::B()
A::~A()
Fin
只要您不尝试释放尚未分配的资源,按照您在问题中所示的方式手动调用析构函数就是安全的。最好将这些资源包装在某种类型的 RAII
容器中(std::auto_ptr
、boost::shared_ptr
等)以避免必要性调用析构函数。
Mooing Duck 提供了一个非常好的说明,说明当构造函数中抛出异常时堆栈展开如何工作:
关于c++ - 派生类构造函数中的异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7352833/