好的StackOverflow民谣。
有没有更好的方法来处理成员变量构造函数中的异常?我不得不与一个库类进行交互,这个类可能会也可能不会在它的构造函数中抛出异常(无法提前检查)并且我想避免在我的类中使用指针(如果发生了崩溃) ,我希望所有析构函数都被正确调用,即使我搞砸了)。我目前已经确定了这个实现(例如,包括一个虚拟存根):
class class_I_have_no_control_over{
public:
class_I_have_no_control_over( int someArgument )
{
if( someInternalConditionThatCantBeTestedExternally )
throw anException;
}
class_I_have_no_control_over( )
{ //Does not throw
}
}
class MyClass{
private:
class_I_have_no_control_over memberVariable;
public:
MyClass()
{
try{
class_I_have_no_control_over tempVariable( 24 );
memberVariable = std::move( tempVariable );
}catch(...)
{
class_I_have_no_control_over tempVariable( );
memberVariable = std::move( tempVariable );
}
}
}
我考虑的第一种方法是try catch初始化列表:即
class MyClass{
private:
OtherClassThatTrowsOnConstruct member;
MyClass()
try:
member()
{//Normal constructor
}
catch(...)
{//Can translate an exception but cant stop it.
}
但是该方法只能用于转换异常,而不是停止它们(如果你不抛出异常,运行时将重新抛出原始异常)。
有些人会说使用动态分配(即带有new和delete关键字的指针),但是当这个库处理进程之间的共享内存时,我有点厌倦了崩溃时动态内存内容会发生什么。其中一个应用程序(例如,析构函数从未被调用,另一个应用程序正在等待不再运行的应用程序,从未意识到它不再在监听)。
答案 0 :(得分:0)
可以稍微简化第一个版本,而不改变其行为:
MyClass() try {
memberVariable = class_I_have_no_control_over(24); // move from temporary
} catch (...) {
// no need to do anything; memberVariable is already default-constructed
// Unless the class is so evil that move-assignment might fail and leave
// the target in a messed-up state. In which case you probably want
memberVariable = class_I_have_no_control_over();
// If that fails, you should probably give up and let the exception go.
}
除非你有进一步的限制(例如课程不可移动),否则这是处理你情况的最佳方法。如果它是不可移动的,那么动态分配可能是一个合理的选择;使用智能指针(可能是std::unique_ptr
)来确保它与MyClass
对象一起被销毁。
#include <memory>
class MyClass{
private:
std::unique_ptr<unmovable_evil> memberVariable;
public:
MyClass() try {
memberVariable.reset(new unmovable_evil(24));
} catch(...) {
memberVariable.reset(new unmovable_evil);
}
};
您可能还会将boost::optional
视为动态分配的非标准替代方案。