使用异常时,C++代码变为非线性

Epi*_*lle 1 c++ exception raii

我的项目主要看起来像那样

Object a;

if (! a.initialize(x, y, z))
  return EXIT_FAILURE;

// 100 lines using a

a.finalize();
Run Code Online (Sandbox Code Playgroud)

我试图改变这部分代码并使用RAII idiome.所以,我删除了initialize函数,finalize并在构造函数和析构函数中移动代码.

为了捕获initialize()错误,如果出现故障,我会在构造函数中抛出异常.

所以现在,我的代码是这样的:

try
{
  Object a(x, y, z);

  // 100 lines using a
} catch (my_exception&)
{
  return EXIT_FAILURE;
}
Run Code Online (Sandbox Code Playgroud)

认为麻烦的是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();
Run Code Online (Sandbox Code Playgroud)

现在它看起来很难看,难以阅读:

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;
}
Run Code Online (Sandbox Code Playgroud)

如何使用RAII并保持代码清晰?

Mik*_*our 5

通常,在要处理异常的级别创建一个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;
}
Run Code Online (Sandbox Code Playgroud)

现在它不是"一个错误太长"; 对于可能发生的任何错误,它是正确的长度.

将自己局限于源自的异常是一个好主意std::exception; 那么你可以在没有处理的情况下给出一些可能有用的信息:

catch (std::exception const & ex) {
    std::cerr << "ERROR: " << ex.what() << std::endl;
    return EXIT_FAILURE;
}
Run Code Online (Sandbox Code Playgroud)