在C++中从错误条件退出构造函数的最佳技术是什么?特别是,打开文件时出错.
谢谢你的回复.我正在抛出异常.这是代码(不知道它是否是最好的方法,但它很简单)
// Test to see if file is now open; die otherwise
if ( !file.is_open() ) {
cerr << "Failed to open file: " << m_filename << endl;
throw ("Failed to open file");
}
Run Code Online (Sandbox Code Playgroud)
有人认为我喜欢C++,你不必在方法声明上声明抛出的异常.
Bri*_*ndy 27
最好的建议可能是parashift所说的.但请阅读下面的注意事项.
[17.2]如何处理失败的构造函数?
抛出一个例外.
构造函数没有返回类型,因此无法使用返回代码.因此,表示构造函数失败的最佳方法是抛出异常.如果您没有使用异常的选项,那么"最不好"的解决方法是通过设置内部状态位将对象置于"僵尸"状态,这样对象的行为有点像死了,即使它是技术上还活着.
"僵尸"对象的想法有很多不足之处.你需要添加一个查询("督察")成员函数来检查这个"僵尸"位,这样你班级的用户就可以知道他们的对象是否真的存活,或者它是一个僵尸(即一个"活死人"对象) ,几乎每个你构建一个对象的地方(包括在一个更大的对象或一个对象数组中),你需要通过if语句检查那个状态标志.你还需要为你的其他成员函数添加一个if:如果对象是一个僵尸,那么做一个no-op或者更令人讨厌的东西.
在实践中,"僵尸"的东西变得非常难看.当然你应该比zombie对象更喜欢异常,但是如果你没有使用异常的选项,那么僵尸对象可能是"最不好"的选择.
在构造函数中抛出异常时要小心谨慎:
但要非常小心,因为如果在构造函数中抛出异常,则不会调用类的析构函数.因此,在抛出异常之前,需要注意破坏已经构造的对象.一般来说,相同的警告适用于异常处理,但在处理构造函数时,它可能稍微不那么明显.
class B
{
public:
B()
{
}
virtual ~B()
{
//called after D's constructor's exception is called
}
};
class D : public B
{
public:
D()
{
p = new char[1024];
throw std::exception("test");
}
~D()
{
delete[] p;
//never called, so p causes a memory leak
}
char *p;
};
int main(int argc, char **argv)
{
B *p;
try
{
p = new D();
}
catch(...)
{
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
使用CreateInstance方法的受保护/私有构造函数:
另一种方法是使您的构造函数成为私有或受保护的,并创建一个可以返回错误的CreateInstance方法.
您可以像其他人提到的那样抛出异常,或者您也可以重构代码,以便构造函数不会失败.例如,如果您正在处理禁用或禁止例外的项目,那么后者是您的最佳选择.
要创建一个不会失败的构造函数,重构可能会失败的代码init(),并让构造函数尽可能少地工作,然后要求所有类的用户init()在构造后立即调用.如果init()失败,您可以返回错误代码.请务必在课程文档中记录这一点!
当然,这有点危险,因为程序员可能会忘记打电话init().编译器无法强制执行此操作,因此请谨慎操作,并尝试在init()未调用时使代码快速失败.