如何避免在catch块中写入重复的代码?

时间:2012-04-21 06:40:00

标签: c++ optimization exception-handling try-catch throw

我正在使用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块中编写清理代码吗? 有什么方法可以避免编写重复的代码

注意 :: [在method1()]我想重新抛出发生的异常            我的来电者。所以我无法在单一的捕获区中捕获它们,            因为那时类型信息将会丢失。

3 个答案:

答案 0 :(得分:8)

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

  1. RAII。将任何清理代码放入析构函数中,清理代码将集中。
  2. 使用不合格的throw,您无需了解抛出的异常类型。
  3. 因此,method1()应如下所示:

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

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

答案 1 :(得分:1)

您应该尽可能地抛出异常,并在调用链中尽可能高地捕获它们。这会自动减少代码重复,并集中处理错误。你在一个地方投掷/捕捉,这似乎有点......被迫。

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

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";
}

这只能用于抛出您不打算更好地处理的异常或重试失败的操作等。

这种方法的专家是所有/大多数错误处理代码都在程序的顶层,并且调用链中的所有函数都不必担心这些东西,他们所做的只是当他们有这种感觉时抛出异常。

答案 2 :(得分:0)

如果所有清理代码完全相同,则可以执行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;
}