C++ C++;使用异常时,代码变得非线性
我有一个项目,它的主体看起来是这样的C++ C++;使用异常时,代码变得非线性,c++,exception,raii,C++,Exception,Raii,我有一个项目,它的主体看起来是这样的 Object a; if (! a.initialize(x, y, z)) return EXIT_FAILURE; // 100 lines using a a.finalize(); 我正在尝试更改这部分代码,并使用RAII-idiome。 因此,我删除initialize函数和finalize并将代码移动到构造函数和析构函数中 为了捕获initialize()错误,如果有什么失败,我会在构造函数中抛出一个异常 现在,我的代码是这样的: t
Object a;
if (! a.initialize(x, y, z))
return EXIT_FAILURE;
// 100 lines using a
a.finalize();
我正在尝试更改这部分代码,并使用RAII-idiome。
因此,我删除initialize
函数和finalize
并将代码移动到构造函数和析构函数中
为了捕获initialize()
错误,如果有什么失败,我会在构造函数中抛出一个异常
现在,我的代码是这样的:
try
{
Object a(x, y, z);
// 100 lines using a
} catch (my_exception&)
{
return EXIT_FAILURE;
}
最麻烦的是100行代码。我的try
太长,不能只出现一个错误。我有多个对象,比如a
所以在我的代码是线性的之前:
Object a;
if (! a.initialize(x, y, z))
return EXIT_FAILURE;
Object b;
Object c;
if (!b.initialize() || !c.initialize())
return EXIT_FAILURE;
a.finalize();
现在它看起来很难看,很难读:
try
{
Object a(x, y, z);
try
{
Object b;
try
{
Object c;
}
catch (my_exception_c&)
{
return EXIT_FAILURE;
}
}
catch (my_exception_b&)
{
return EXIT_FAILURE;
}
} catch (my_exception&)
{
return EXIT_FAILURE;
}
如何使用RAII并保持代码清晰?通常,在要处理异常的级别创建一个try块。在这种情况下,您只需要一个顶级块来清除任何异常:
try {
Object a(x, y, z);
Object b;
Object c;
// code using these
} catch (...) {
// end the program if any exception hasn't been handled
return EXIT_FAILURE;
}
现在它不是“一个错误的时间太长”;对于可能发生的任何错误,它都是正确的长度
最好将自己限制为从std::exception
派生的异常;然后,您可以在未处理的情况下提供一些潜在有用的信息:
catch (std::exception const & ex) {
std::cerr << "ERROR: " << ex.what() << std::endl;
return EXIT_FAILURE;
}
catch(std::exception const&ex){
std::cerr通常,在您想要处理异常的级别创建一个try块。在这种情况下,您只需要一个顶级块来清理任何异常:
try {
Object a(x, y, z);
Object b;
Object c;
// code using these
} catch (...) {
// end the program if any exception hasn't been handled
return EXIT_FAILURE;
}
现在,它不是“对于一个错误来说太长”,而是对于任何可能发生的错误来说都是正确的长度
最好将自己限制为从std::exception
派生的异常;然后在未处理的情况下,您可以提供一些潜在有用的信息:
catch (std::exception const & ex) {
std::cerr << "ERROR: " << ex.what() << std::endl;
return EXIT_FAILURE;
}
catch(std::exception const&ex){
std::cerr您只需要一个这样的捕获:
try
{
Object a;
Object b;
//100 lines of code
}
catch(ExeptionA& exa)
{
cerr << "error a" << endl;
}
catch(ExeptionB& exa)
{
cerr << "error B" << endl;
}
catch(...){
cerr << "some other error" << endl;
}
试试看
{
对象a;
对象b;
//100行代码
}
捕获(例外a和exa)
{
cerr您只需要一次这样的捕获:
try
{
Object a;
Object b;
//100 lines of code
}
catch(ExeptionA& exa)
{
cerr << "error a" << endl;
}
catch(ExeptionB& exa)
{
cerr << "error B" << endl;
}
catch(...){
cerr << "some other error" << endl;
}
试试看
{
对象a;
对象b;
//100行代码
}
捕获(例外a和exa)
{
cerr您可以始终拥有另一个函数,如“IsValid()”,在调用构造函数后进行检查,而不是抛出异常。您可以保留RAII(异常安全、防止初始化/销毁错误等)的优点,但您可以使代码保持与以前相同的格式。
在C++的好实践中,它不是干净和安全的,因为用户可以忘记检查它是否有效,但是选项是存在的。你总是可以有一个函数,比如“ISUVE()”,在调用构造函数之后检查,而不是抛出异常。(异常安全、防止初始化/销毁错误等),但您将能够保持代码的格式与以前相同。
对于C++的好实践来说,它不是干净和安全的,因为用户可以忘记检查它是否有效,但是选项是存在的。非纯RAII是一个CBOTS可以在不抛出的情况下失败的原因,RAII对象记录了这样的失败。它看起来像是两个例子的混合,但是资源清理在返回错误子句中是自动的。非纯RAII是一种CTOR可以在不抛出的情况下失败的方法,RAII对象记录了这种失败。它看起来像是两个示例的混合体,但在return error子句中,资源清理是自动的。