我能做到這一點,沒有任何問題:爲什麼的try ... catch需要確切類型拋出
long lngval = 3L;
int i = lngval;
但如果我試試這個:
try {
throw 3L;
}
catch(int i) {
cout << "caught " << i << endl;
}
我得到一個未處理的異常。
這似乎不一致。在這種情況下沒有類型轉換的原因是什麼?
我能做到這一點,沒有任何問題:爲什麼的try ... catch需要確切類型拋出
long lngval = 3L;
int i = lngval;
但如果我試試這個:
try {
throw 3L;
}
catch(int i) {
cout << "caught " << i << endl;
}
我得到一個未處理的異常。
這似乎不一致。在這種情況下沒有類型轉換的原因是什麼?
在第一種情況下,編譯器可以準確地知道你想要做什麼:將long
轉換爲int
。在第二種情況下,編譯器必須假設,你可能有這樣的結構:
try {
try {
throw 3L;
}
catch (int i) { /* P */ }
}
catch (long l) { /* Q */ }
的想法是,編譯器無法知道是否有可能是一個catch (long l)
潛伏在當前的上下文之外,所以它永遠不會安全地選擇第一個可能的轉換。
這也是爲什麼它的共同拋出異常時,而不是隨機的類型,如int
或long
使用類層次結構:它可以很容易地以這樣的方式,編譯器可以或多或少規範添加到您的異常處理程序確定你的意圖(通過is-a關係)。
您可以在一個try-catch塊中捕獲多個類型。爲了讓編譯器知道要拋出哪個catch塊,它必須能夠匹配確切的類型。或者它可以有一個默認的catch塊 - catch (...) {}
,但是你將無法得到這種情況下拋出的值。
catch語句在給定類型的情況下捕獲一個對象(或者標量變量),所以如果類型不匹配,它將傳遞給下一個catch語句(如果有的話)或默認的異常接收者。
就你而言,你可以有第二個catch語句捕獲很長時間,也許在別的地方,所以你的catch語句不會捕獲任何東西。
捕捉任何異常,只是使用捕捉(){} :)
單尖,更好的使用異常類,或者繼承它適合你自己的需要:)
你也可以throw 3;
- 沒問題。
int
和long
是不同的類型。除了查看它們的類型之外,異常處理的一個優點是可以告訴異常(一箇中央try塊可以處理來自各個地方的各種異常/ try塊可以處理某些類型的異常,讓其他異常傳播)。
此外,建議拋出其中一個標準異常或從其中一個類派生類。那麼如果你只是想處理這個異常並且不關心這個特定的類型,那麼你就可以只用catch (const std::exception&)
。
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。
發表100次:「我只會拋出派生自std :: exception的對象」 –
@Tadeusz除了拋出一個'int'來終止一個程序的常見習語之外。 ('main'包含'try ... catch'來捕獲int並返回它,這個習慣用法和調用'exit' **的效果相同,除了調用了所有局部變量的析構函數。 –
@JamesKanze:有趣的是,我不知道這個成語。我確實看到了一種從無到有繼承的「SuicideException」,一次,我會猜你的角色。在這兩種情況下,儘管你確實沒有人寫過「catch(...)」子句。 –