【发布时间】:2011-03-24 14:42:33
【问题描述】:
我想调用一个可能引发异常的函数。如果它确实引发了异常,我想捕获它并将异常对象传递给处理函数。处理函数的默认实现只是抛出异常。以下是用于说明问题的精简代码:
struct base_exception : exception {
char const* what() const throw() { return "base_exception"; }
};
struct derived_exception : base_exception {
char const* what() const throw() { return "derived_exception"; }
};
void exception_handler( base_exception const &e ) {
throw e; // always throws a base_exception object even if e is a derived_exception
}
int main() {
try {
throw derived_exception();
}
catch ( base_exception const &e ) {
try {
cout << e.what() << endl; // prints "derived_exception" as expected
exception_handler( e );
}
catch ( base_exception const &e ) {
cout << e.what() << endl; // prints "base_exception" due to object slicing
}
}
}
但是,exception_handler() 中的throw e 会抛出异常的静态类型的副本,即base_exception。我怎样才能让exception_handler() 抛出具有derived_exception 正确运行时类型的实际 异常?或者我怎样才能重新设计东西以获得我想要的东西?
【问题讨论】:
-
将
throw e;更改为throw; -
顺便说一句:有什么方法可以防止异常切片(例如,通过编译时错误)?程序员很容易输入“e”并得到错误的行为。
-
@Paul J. Lucas:您可以尝试使异常不可复制
-
@Erik:C++ 标准要求所有异常对象都具有可访问的复制构造函数:“当抛出的对象是类对象,并且用于初始化临时副本的复制构造函数不可访问时,程序格式错误(即使临时对象可以被消除)。”
-
@Paul J. Lucas:那就不知道了——也许是
throw new foo和 catch 指针。我认为一个人应该得到一个新的 Q。