为什么使用boost :: copy_exception时会丢失类型信息?
当我使用boost::copy_exception
将例外复制到exception_ptr
时,我丢失了类型信息。看看下面的代码:为什么使用boost :: copy_exception时会丢失类型信息?
try {
throw std::runtime_error("something");
} catch (exception& e) {
ptr = boost::copy_exception(e);
}
if (ptr) {
try {
boost::rethrow_exception(ptr);
} catch (std::exception& e) {
cout << e.what() << endl;
cout << boost::diagnostic_information(e) << endl;
}
}
由此,我得到下面的输出:
N5boost16exception_detail10clone_implISt9exceptionEE
Dynamic exception type: boost::exception_detail::clone_impl<std::exception>
std::exception::what: N5boost16exception_detail10clone_implISt9exceptionEE
所以基本上boost::copy_exception
静态复制它得到了论证。
如果我用boost::enable_current_exception
来代替这个问题,这个问题就解决了。
try {
throw boost::enable_current_exception(std::runtime_error("something"));
} catch (...) {
ptr = boost::current_exception();
}
if (ptr) {
try {
boost::rethrow_exception(ptr);
} catch (std::exception& e) {
cout << e.what() << endl;
cout << boost::diagnostic_information(e) << endl;
}
}
问题在于,有时例外情况是由不使用boost::enable_current_exception
的库引发的。在这种情况下,除了逐一捕捉每种可能的例外情况并在每一种情况下使用boost::copy_exception
之外,是否有任何方法可将异常置入exception_ptr
?
这是设计,你的分析是正确的:使用静态类型,而不是动态类型。实际上,为了避免这种意外,在导致C++ 11的过程中,boost::copy_exception
变成了std::make_exception_ptr
。这样,current_exception
(无论Boost版本还是C++ 11版本)是正确的事情,正确地捕获当前的异常。在代码中使用启用Boost.Exception的异常时,强烈建议使用BOOST_THROW_EXCEPTION
或至少boost::throw_exception
。
对于第三方代码,除了您已经提到的代码或其他一些道德等价物(如dynamic_cast
-对构成异常类型层次结构或层次结构的不同叶子类,或者typeid
滥用)。
在这方面,异常处理与使用一个或多个多态类型的层次结构相同,并且您在此尝试的操作是虚拟副本,也称为克隆:您的代码可能被设计为侵入式支持(如使用例如BOOST_THROW_EXCEPTION(e);
而不是throw e;
),或者你会痛苦地走继承树。请注意,您至少可以将这种痛苦重构为只有一个网站,这样您最终可以
try {
third_party_api();
} catch(...) {
ptr = catch_exceptions_from_api();
}
我不是很熟悉boost异常,但是你在'catch'块中尝试了一个简单的'throw;',它在抛出当前异常的同时又保留了它的类型吗? – Asha 2012-04-02 09:04:03
你可能正在遭受[切片](http://stackoverflow.com/questions/274626/what-is-the-slicing-problem-in-c)问题。 – enobayram 2012-04-02 09:07:57