2010-03-17 78 views
22

C++中是否定义好了?我被迫'异常'转换为返回代码(许多C用户使用该API,因此我需要确保在控制返回给调用者之前处理所有C++异常都被捕获&)。在嵌套的'try'中重新抛出合法的异常吗?

enum ErrorCode {…}; 
ErrorCode dispatcher() { 
    try { 
     throw; 
    } 
    catch (std::bad_alloc&) { 
     return ErrorCode_OutOfMemory; 
    } 
    catch (std::logic_error&) { 
     return ErrorCode_LogicError; 
    } 
    catch (myownstdexcderivedclass&) { 
     return ErrorCode_42; 
    } 
    catch(...) { 
     return ErrorCode_UnknownWeWillAllDie; 
    } 
} 

ErrorCode apifunc() { 
    try { 
     // foo() might throw anything 
     foo(); 
    } 
    catch(...) { 
     // dispatcher rethrows the exception and does fine-grained handling 
     return dispatcher(); 
    } 
    return ErrorCode_Fine; 
} 

ErrorCode apifunc2() { 
    try { 
     // bar() might throw anything 
     bar(); 
    } 
    catch(...) { 
     return dispatcher(); 
    } 
    return ErrorCode_Fine; 
} 

我希望样本能显示我的意图。我的猜测是这是未定义的行为,但我不确定。如果适用,请提供标准报价。备选方法也受到赞赏。

谢谢!

+1

我记得考虑采用这种方法来减少来自不同try/catch块的代码重复,但我实现了它。是什么让你认为这可能是非法的? – 2010-03-17 21:50:55

+0

我也曾使用过这个技巧 – iain 2010-03-17 22:26:25

+2

@jdv - 我感觉有点不舒服,从嵌套在catch-clause(甚至在不同的堆栈框架)中的try块中重新抛出。它看起来有点太漂亮了,所以我想保持安全。 – 2010-03-17 22:34:02

回答

12

这很好。异常处于活动状态,直到它被捕获,它变为非活动状态。但是它会一直存在,直到处理程序的作用域结束。从标准,重点煤矿:

15.1节/ 4: 可能抛出在未指定的方式分配,除非在3.7.4.1指出的异常的临时副本的内存。 只要有为该异常执行的处理程序,临时存在。

即:

catch(...) 
{ // <-- 

    /* ... */ 

} // <-- 

这些箭头之间,你可以重新抛出异常。只有当处理程序范围结束时,异常消失。

请记住,如果您拨打dispatch而没有激活的例外情况,terminate将被调用。如果dispatch在其中一个处理程序中抛出异常,则异常将开始传播。更多信息在a related question

+0

在构造函数中调用的方法中使用这个approuch可能会好吗? (克++) – agodinhost 2015-09-08 13:35:35

2

由于dispatcher在catch块中调用throw会重新抛出异常。如果您将致电dispatcher外部catch块,然后将调用terminate()(根据15.1/8)。在任何情况下都没有不确定的行为。