2010-03-17 72 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)。在任何情況下都沒有不確定的行爲。