2012-04-02 57 views
2

当我使用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

+0

我不是很熟悉boost异常,但是你在'catch'块中尝试了一个简单的'throw;',它在抛出当前异常的同时又保留了它的类型吗? – Asha 2012-04-02 09:04:03

+0

你可能正在遭受[切片](http://stackoverflow.com/questions/274626/what-is-the-slicing-problem-in-c)问题。 – enobayram 2012-04-02 09:07:57

回答

4

这是设计,你的分析是正确的:使用静态类型,而不是动态类型。实际上,为了避免这种意外,在导致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(); 
} 
相关问题