catch (...)
是一個所謂的「catch all」塊。它會捕獲任何 C++異常。
catch(std::exception& e)
將捕獲只有從std::exception
派生的例外。
這裏是一個將被捕獲所有被稱爲一個例外的例子,但不是第二個版本:
throw 42;
這聽起來很奇怪,你,它是。要認識到的重要一點是,任何東西都可以作爲C++異常拋出 - 不僅僅是exception
或從exception
派生的東西。正如@ bames53在註釋中提到的那樣,沒有任何異常類型來源於所有異常,就像其他語言一樣。
重要的是要注意,一個全通塊很容易被濫用。事實上,作爲一般的經驗法則,最好假設所有全部封鎖都是程序缺陷。當然,編程中並沒有「永遠」,但是當你學習使用異常時,這是一個安全的假設。
爲什麼catch-all模塊是邪惡的原因是因爲它們通常如何使用。通常情況下,一個天真的程序員會編寫一個捕獲所有程序來試圖捕捉任何編程錯誤,然後批判地繼續讓程序運行,就好像什麼也沒發生一樣。這是一場等待發生的災難。程序狀態現在是不確定的。某個地方出了問題。你不能安全地忽略異常,並繼續像一切都很好。即使你的程序繼續運行,可能會在某處發生微妙的堆損壞,會摻雜程序的計算或其輸出。發生堆損壞時,作爲程序員可以希望的最好的事情是立即崩潰。這樣你就可以在腐敗點得到一個調用堆棧和一個轉儲文件,並找到並解決問題。但是,當你有一個全面的地方,你已經失去了腐敗發生的所有背景。在你的代碼中找到真正的缺陷幾乎是不可能的。
當然,捕獲所有處理程序是有效的和有價值的用法。最常見的一種情況是編寫一個全局異常處理程序,然後重新編號爲throw
。這個全局處理程序可以啓動某種故障記錄,可能是通過記錄錯誤本身,或者產生一個外部程序來記錄失敗程序以外的記錄。通過重新拋出異常,您可以爲委託人提供處理可以處理的異常的機會,同時允許無法處理的異常終止程序。
重新執行異常很簡單。只需撥打throw
不帶參數,如:
catch (...)
{
// some magic
throw;
}
另一件事要記住的是,當你做捕獲一個例外,它通常最好趕const
參考,而不是隻是一個參考。
C++沒有 '根' 的異常類型所有異常繼承,因爲C++可以拋出任何東西,包括不能繼承的類型;例如'int'。 C++可以拋出任何東西,因爲他們沒有看到讓異常變得不那麼普遍的理由。它類似於C++模板; C++模板不依賴於繼承,因此比一般依賴繼承的Java或C#泛型更通用。 – bames53
某些Windows SEH異常有時可能被'...'發現,但不會被'std :: exception'發現。只有當你瘋狂的標誌編譯,使用推薦/ EHSC(如果可以的話),你會被罰款 –
@MooingDuck –