2016-02-05 58 views
0

我有一個小問題,我無法用乾淨的方式解決。 我正在嘗試一些多態異常處理,所以我在我的異常類中添加了一個提升虛擬函數,用於實際投擲,並用raise()調用替換了投擲。 一切正常,但然後我應用這個解決方案的功能與返回類型具有以下一般形式:多態異常處理和編譯器警告

Obj Foo() 
{ 
    if(true) 
    return Obj 
    else 
    { 
    //throw Exception; //With this call everything is fine 
    Exception e{}; 
    e.raise(); //The compiler warns me that I do not return anything 
    } 
} 

當我編譯這種功能的GCC編譯器(V4.9)抱怨富到達沒有返回結束(-Wreturn-type) 有沒有辦法說服編譯器,一切正常,沒有隱藏警告呢?

+0

_是否有辦法讓編譯器確信一切正常,而不會將警告隱藏起來?_是不是不相交? – erip

+0

多態異常?爲什麼?派生自'std :: runtime_error'或'std :: logic_error'。然後拋出你想拋出的異常 - 每個問題類型一個異常類型。 –

+0

@erip:它們不是不相交的,因爲一切都確實沒問題,如果我將raise函數的throw語句帶到body中,編譯器會認識到所有的執行路徑都會正確返回。如果它隱藏在raise()函數中,編譯器會抱怨 – Triskeldeian

回答

1

爲了避免這種情況,可以使函數中的每個控制路徑返回與返回類型一致的東西,即使某些條件可以始終顯示爲有效,或者某些路徑可以顯示爲始終引發異常。在這裏,你的else路徑沒有Obj類型的返回值。

因此,您的e.raise()之後,您可以返回一些值。如果無法創建合適的值,請考慮讓函數返回optional<obj>

+1

「每個控制路徑都需要返回...」 - 不,這不是必需的。只有當返回的值被使用**時,函數才能返回一些合理的值。通過拋出異常退出函數沒有任何問題,不管它是由'throw'還是通過函數調用完成的,其目的是拋出異常。這裏的問題是一個非常有用的編譯器,它應用了非規則。 –

+0

謝謝,@PeteBecker我認爲你是對的。會相應更新。 –

+0

@Pete Becker:+1。唯一的問題是編譯器實際上並沒有應用約束,只是警告。儘管如此,你是對的 – Triskeldeian

1

如果你不需要的便攜性,以及使用gcc的編譯器擴展都很好,那麼你可以使用gcc noreturn function attribute,這與C和C++功能的工作原理:

class Exception { 

// ... 

    void raise() __attribute__ ((noreturn)); 

}; 
+0

我想保持便攜,但很高興知道,謝謝 – Triskeldeian

2

我認爲Exception.raise()拋出一個異常,並且您正在使用true來表示某個表達式,該表達式確定是否不拋出異常(而不是C++關鍵字)。 (因爲你沒有提到編譯器抱怨總是這樣的情況)。

顯而易見的解決方案是在拋出異常之後添加return語句。

Exception e{}; 
e.raise(); 
return Obj; // this will not be reached 

另一種方法是調整你的代碼,所以總有一個返回路徑

if (!true) 
{ 
    Exception e{}; 
    e.raise();  // or, alternatively, throw e 
} 
return Obj; 

這樣,編譯器可以檢測到每個執行路徑,有一個有效的return語句。

+0

這對我來說似乎是最合理的。 – erip

+0

確實,第二種選擇可能是唯一合理的方法。 我曾考慮過第一種選擇,但我不喜歡「間諜價值」,即使它們從未實際使用過。這就是爲什麼我特意說「一種乾淨的方式」 – Triskeldeian