我想调用一个可能抛出异常的函数。如果它确实抛出异常,我想捕获它并将异常对象传递给处理函数。处理函数的默认实现只是抛出异常。以下是用于说明问题的简化代码:
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
}
}
}
但是,throw e
中的exception_handler()
会抛出异常的静态类型的副本,即base_exception
。如何使exception_handler()
抛出具有正确运行时类型derived_exception
的实际异常?或者我如何重新设计东西以获得我想要的东西?
答案 0 :(得分:3)
您可以在基本异常类中放置一个throw_me
虚函数,并让每个派生类都覆盖它。派生类可以抛出适当的派生类型,而不进行切片。即使函数在每个类中具有相同的定义,它们也不相同 - *this
的类型在每种情况下都不同。
struct base_exception : exception
{
char const* what() const throw() { return "base_exception"; }
virtual void throw_me() const { throw *this; }
};
struct derived_exception : base_exception
{
char const* what() const throw() { return "derived_exception"; }
virtual void throw_me() const { throw *this; }
};
void exception_handler( base_exception const &e ) {
e.throw_me();
}
答案 1 :(得分:2)
您可以使用throw;
重新抛出已捕获的异常。您也可以使用模板。
template<typename T> void rethrow(const T& t) { throw t; }
答案 2 :(得分:0)
Throw by value, catch by reference。它会为你省去很多麻烦。
答案 3 :(得分:-1)
您正在寻找的内容称为“传播”异常。为此,您必须使用throw
块中没有参数的catch
关键字。它不会复制异常,并且异常将在下一个catch
块中被捕获,或者如果它没有被捕获则会使程序中止。