2011-09-27 55 views
8

我能做到這一點,沒有任何問題:爲什麼的try ... catch需要確切類型拋出

long lngval = 3L; 
int i = lngval; 

但如果我試試這個:

try { 
    throw 3L; 
} 

catch(int i) { 
    cout << "caught " << i << endl; 
} 

我得到一個未處理的異常。

這似乎不一致。在這種情況下沒有類型轉換的原因是什麼?

+6

發表100次:「我只會拋出派生自std :: exception的對象」 –

+1

@Tadeusz除了拋出一個'int'來終止一個程序的常見習語之外。 ('main'包含'try ... catch'來捕獲int並返回它,這個習慣用法和調用'exit' **的效果相同,除了調用了所有局部變量的析構函數。 –

+0

@JamesKanze:有趣的是,我不知道這個成語。我確實看到了一種從無到有繼承的「SuicideException」,一次,我會猜你的角色。在這兩種情況下,儘管你確實沒有人寫過「catch(...)」子句。 –

回答

7

在第一種情況下,編譯器可以準確地知道你想要做什麼:將long轉換爲int。在第二種情況下,編譯器必須假設,你可能有這樣的結構:

try { 
    try { 
    throw 3L; 
    } 
    catch (int i) { /* P */ } 
} 
catch (long l) { /* Q */ } 

的想法是,編譯器無法知道是否有可能是一個catch (long l)潛伏在當前的上下文之外,所以它永遠不會安全地選擇第一個可能的轉換。

這也是爲什麼它的共同拋出異常時,而不是隨機的類型,如intlong使用類層次結構:它可以很容易地以這樣的方式,編譯器可以或多或少規範添加到您的異常處理程序確定你的意圖(通過is-a關係)。

0

您可以在一個try-catch塊中捕獲多個類型。爲了讓編譯器知道要拋出哪個catch塊,它必須能夠匹配確切的類型。或者它可以有一個默認的catch塊 - catch (...) {},但是你將無法得到這種情況下拋出的值。

1

catch語句在給定類型的情況下捕獲一個對象(或者標量變量),所以如果類型不匹配,它將傳遞給下一個catch語句(如果有的話)或默認的異常接收者。

就你而言,你可以有第二個catch語句捕獲很長時間,也許在別的地方,所以你的catch語句不會捕獲任何東西。

捕捉任何異常,只是使用捕捉(){} :)

單尖,更好的使用異常類,或者繼承它適合你自己的需要:)

1

你也可以throw 3; - 沒問題。

intlong是不同的類型。除了查看它們的類型之外,異常處理的一個優點是可以告訴異常(一箇中央try塊可以處理來自各個地方的各種異常/ try塊可以處理某些類型的異常,讓其他異常傳播)。

此外,建議拋出其中一個標準異常或從其中一個類派生類。那麼如果你只是想處理這個異常並且不關心這個特定的類型,那麼你就可以只用catch (const std::exception&)

4

catch確實不是必然需要確切的類型。

使用從std::exception派生的例外(在<stdexcept>中找到)是常見的和良好的做法。原因是,你可以多形地捕捉,即你做而不是需要知道確切的類型(另見Difference: std::runtime_error vs std::exception()),並且我們有一個約定來處理這個。

無論您使用的標準(例如:std::range_error)提供者之一,或者如果沒有適合您的問題[足夠],專門std::exception

#include <stdexcept> 

class moores_law_stopped : public std::exception { 
public: 
    virtual ~moores_law_stopped() throw() {} 
    virtual const char *what() const throw() { 
     return "moores law stopped. duck under your table."; 
    } 
}; 



#include <iostream> 
int main() { 
    try { 
     throw moores_law_stopped(); 
    } catch (std::exception const &e) { 
     std::cerr << "oh oh: " << e.what() << std::endl; 
    } 
} 

輸出:

oh oh: moores law stopped. duck under your table. 

的約定是通過引用或const引用來捕獲的,這樣就可以獲得多態行爲而不用擔心object slicing