C++ 巢狀異常
阿新 • • 發佈:2019-01-06
當處理第一個異常時,可能會觸發第二種異常情況,從而要求丟擲第二個異常。遺憾的是,當丟擲第二個異常時,正在處理的第一個異常的所有資訊都會丟失。C++用巢狀異常(nested exception)的概念提供瞭解決這一問題的方案,巢狀異常允許將捕獲的異常巢狀到新的異常環境。使用std::throw_nested()可以丟擲嵌套了異常的異常。第二個異常的catch處理程式可以使用dynamic_cast訪問代表第一個異常的nested_exception。下面的示例演示了巢狀異常的用法。這個示例定義了一個從exception派生的MyExcepion類,其建構函式接受一個字串。
#pragma once #include<exception> #include<iostream> #include<string> using namespace std; class MyException :public exception { public: MyException(const char* msg) :mMsg(msg) {} virtual ~MyException()noexcept {} virtual const char* what() const noexcept override { return mMsg.c_str(); } private: string mMsg; };
當處理第一個異常,且需要丟擲嵌套了第一個異常的第二個異常時,需要使用std::throw_with_nested()函式。下面的doSomething()函式排除一個runtime_error異常,這個異常立即被處理程式捕獲。捕獲處理程式編寫了一條訊息,然後使用throw_with_nested()函式丟擲第二個異常,第一個異常巢狀在其中。注意巢狀異常時自動實現的。
void doSomething() { try { throw runtime_error("Throwing a runtime_error exception"); } catch (const runtime_error&e) { cout << __func__ << " caught a runtime_error" << std::endl; cout << __func__ << " throwing MyException" << endl; throw_with_nested(MyException("MyException with nested runtimeerror)")); }
下面的main()函式演示瞭如果處理具有巢狀異常的異常。這段程式碼呼叫了doSomething()函式,還有一個處理MyException型別異常的處理程式,當捕獲到這類異常時,會編寫一條訊息,然後使用dynamic_cast訪問巢狀的異常。如果內部沒有巢狀異常,結果為空指標。如果you巢狀異常,會呼叫nest_exception的rethrow_nested()方法。這樣會再次丟擲巢狀的異常,這一異常可以在另一個try/catch塊中捕獲。
int main() { try { doSomething(); } catch (const MyException&e) { cout << __func__ << " caught MyException: " << e.what() << endl; const nested_exception *pNested = dynamic_cast<const nested_exception*>(&e); if (pNested) { try { pNested->rethrow_nested(); } catch (const std::runtime_error& e) { //handle nested exception cout << " Nested exception: " << e.what() << endl; } } } return 0; }
輸出結果: