如何避免在 catch 块中编写重复代码

How to avoid writing repeated code in catch blocks?

本文关键字:代码 何避免 catch      更新时间:2023-10-16

我正在使用QT 4.8(C++)进行桌面应用程序项目,并编写异常处理,如下所示:

void callerMethod()
{
  try
  {
   method1();
  }
  catch(Exception1& e)
  {
    // display critcal error message
    // abort application
  }
  catch(std::Exception& e)
  {
   // print exception error message
  }
  catch(...)
  {
   // print unknown exception message
  } 
}
void method1()
{
  try
  {
   // some initializations
   // some operations (here exceptions can occur)
   // clean-up code (for successful operation i.e no exception occurred)
  }
  catch(Exception1& e)
  {
   // clean-up code
   throw e;
  }
  catch(Exception2& e)
  {
   // clean-up code
   throw e;
  }
  catch(Exception3& e)
  {
   // clean-up code
   throw e;
  }
  catch(...)
  {
   // clean-up code
   throw;
  }
}

所以我的问题我需要在每个 catch 块中编写清理代码吗?有什么方法可以避免编写重复的代码吗?

注意:: [ 在方法1() 中 ] 我想重新抛出发生的异常 给我的来电者。所以我不能在单个捕获块中捕获它们, 因为这样类型信息就会丢失。

Method1 可以通过两个概念来简化:

  1. 雷伊。将任何清理代码放入析构函数中,清理代码将被集中化。
  2. 使用非限定throw,您无需知道引发的异常类型。

因此,method1()应如下所示:

void method1()
{
     // some initializations of RAII objects
     // some operations (here exceptions can occur)
}

如果从 std::exception 派生 Exception1,则可以删除 callerMethod 中的第一个 catch 子句,因为 what() 方法是虚拟的。

您应该抛出尽可能低的异常,并在调用链中尽可能高地捕获它们。这会自动减少代码重复,并集中错误处理。你在一个地方扔/接住所有东西,这似乎有点......强迫。

我经常做这种事情(特别是对于程序结束异常:

int main()
try
{
    function_calls_that_may_throw();
    // ...
}
catch(my_exception& e)
{
    e.do_exception_stuff();
}
catch(std::exception& e)
{
    std::cout << e.what();
}
catch(...)
{
    std::cout << "Something bad happened.n";
}

这仅适用于抛出您不打算更好地处理或重试失败操作或其他内容的异常。

这种方法的优点是所有/大多数错误处理代码都位于程序的顶层,调用链中的所有函数都不必担心这些东西,它们所做的只是在他们愿意的时候抛出异常。

如果你所有的清理代码都是完全相同的,你可以在你的catch(...)块中做所有事情:

try {
   // code
} catch (...) {
   // cleanup
   throw;
}

如果代码略有不同,则始终可以调用清理函数:

try {
   // code
} catch (exc1 ex) {
   cleanup(args);
   // exc1 specific
   throw;
} catch (exc2 ex) {
   cleanup(args);
   // exc2 specific
   throw;
} catch (...) {
   cleanup(args);
   throw;
}