2012-04-21 193 views
5

我使用QT 4.8(C++),用于桌面应用程序的项目,并编写异常处理是如下:如何避免在catch块中写入重复的代码?

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()]我想重新抛出异常发生 我caller.So我不能赶上他们在一个catch块, 由于然后键入的信息将会丢失。

+4

Try t o减少使用智能指针,容器类等所需的清理代码的数量。理想情况下,应该没有任何清理代码。 – user763305 2012-04-21 06:43:59

+0

看来你想要做的只是'try {/ * may throw * /} catch(specific_exception const&e){/ * terminate * /}'。如果你不关心异常类型'Exception1','Exception2'等等,那么*不会*捕获它们。 – 2012-04-21 07:54:51

+1

此外,即使你通过引用来捕获,你应该*使用'throw;'rethrow而不是'throw e;'来防止切片。 – ereOn 2012-04-21 08:25:42

回答

8

方法1可以通过两个概念可以大大简化:

  1. RAII。将任何清理代码放入析构函数中,清理代码将被集中。
  2. 使用不合格的throw,您不需要知道抛出的异常类型。

所以,method1()应该是这样的:

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

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

+1

+1。我想说这个。 RAII是这里的解决方案。 – Nawaz 2012-04-21 06:47:23

+0

但我想分别在callerMethod()中处理Exception1。 如果发生Exception1,我想中止应用程序。 – EngineeredBrain 2012-04-21 06:52:12

+0

@AnwarShaikh:你仍然可以做到这一点。 RAII只解决你的清理问题。 – Nawaz 2012-04-21 06:54:50

0

如果你所有的清理代码是完全一样的,你可以在你抓尽一切(...)块:

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; 
} 
+0

如果我写单抛出(..)抛出异常然后,在调用方法我怎么知道哪个异常发生。 因为我想处理中止应用程序的Exception1。 – EngineeredBrain 2012-04-21 06:49:11

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

这对于抛出异常,才可能你不处理好或重试失败的操作什么的计划

这种方法的好处在于,所有/大多数错误处理代码都位于程序的顶层,并且调用链中的所有函数都不必担心这一点,他们所做的只是当他们觉得喜欢时会抛出异常。