1. 程式人生 > >C++ 巢狀異常

C++ 巢狀異常

         當處理第一個異常時,可能會觸發第二種異常情況,從而要求丟擲第二個異常。遺憾的是,當丟擲第二個異常時,正在處理的第一個異常的所有資訊都會丟失。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;
}

輸出結果: