使用C#或Java时,我曾经创建了包含其他异常作为类成员的异常类。例如:
public class MyException : Exception {
private MyException ex;
private String message;
public String what() {
return this.message;
}
public String stack() {
if(ex != null) {
StringBuilder s;
s.append(this.what());
s.append(this.ex.stack());
return s.toString();
}
return this.what();
}
}
我一直在寻找同一主题的例子,但是对于C ++而言我找不到(也许我没有找到正确的术语,因为你可以看到这个问题的标题不是很花哨)。 / p>
无论如何,在C ++中这样做的正确方法是什么?它是将内部异常存储为指针还是引用? (我想我可能需要一个指针,所以当它是第一个异常时它可以为null)。当我引发异常时,它应该是用new
创建的指针吗?
try {
// Code that throws an exception of type MyException
} catch(MyException ex) {
MyException another = new MyException();
another.setEx(ex);
another.setMessage("A message that explains where the other exception was caught and on what conditions");
throw another;
}
答案 0 :(得分:21)
使用C ++ 03中的标准异常没有正确的方法,因为它们被设计为多态使用但无法克隆。因此,如果您抓住std::exception const& e
,可以存储副本,但这会导致切片,丢失所有有用信息。您应该不存储指针或对该异常的引用,因为它的生命周期将在离开catch
子句后立即结束(假设您不重新抛出原始异常)。 / p>
如果您知道可以抛出的每种类型并测试它们,但是这不是一个好的设计(即它颠覆了多态性),您可以解决这个限制。编写一个可以克隆的自己的基本异常类更有意义,并抓住它。如果你抓住来自其他人代码的std::exception
,你仍然会遇到问题。
此时我不得不提及Boost.Exception。它使您可以轻松编写自己的异常层次结构并提供各种实用程序,其中包括boost::exception_ptr
。然后你可以这样做:
typedef boost::error_info<struct tag_nested_exception, boost::exception_ptr>
nested_exception;
// ...
catch(...) {
// better: use BOOST_THROW_EXCEPTION
throw your_exception_type() << nested_exception( boost::current_exception() );
}
这非常有用,boost::diagnostic_info
支持它并将为您显示嵌套异常(它没有记录)。甚至有人建议这个nested_exception
typedef
也应该是图书馆的一部分;与此同时,你自己写的很容易。
不要指望魔术:boost::current_exception
'捕获'活动异常(精细打印:或它的克隆)只有在抛出站点使用boost::enable_current_exception
时才会很好。 (从功能上讲,这是使用可以克隆的基本异常类的道德等价物)。如果没有,它不会失败,但某些信息可能会丢失。
最后请注意,知道C ++ 0x采用了Boost.Exception的设计。因此,以下正确存储活动异常,没有boost::current_exception
警告,因为它有语言支持:
// you can still use Boost.Exception:
typedef boost::error_info<struct tag_nested_exception, std::exception_ptr>
nested_exception;
// ...
catch(...) {
// e has type std::exception_ptr
auto e = std::current_exception();
// internally store the std::exception_ptr
throw your_exception_type(e);
// or with Boost
BOOST_THROW_EXCEPTION( your_exception_type() << nested_exception(e) );
}
还有一种std::nested_exception
类型可以很容易地使用,如下所示:
catch(...) {
// throws an unspecified type derived from your_exception_type
// and std::nested_exception
std::throw_with_nested(your_exception_type());
}
答案 1 :(得分:1)
我猜你可以抛出一个unique_ptr<some_exception>
,然后让inner_exception
另一个unique_ptr
获得所有权。
答案 2 :(得分:0)
如果您的类不是以单例模式设计的,我认为我们不需要Java / C#/ C ++中的类实例属性(即ex
)。此外,here是您可能想要查看的教程。