当处理第一个异常时,可能会触发第二种异常情况,从而要求抛出第二个异常。遗憾的是,当抛出第二个异常时,正在处理的第一个异常的所有信息都会丢失。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;
}
输出结果: