I want to call a function that may throw an exception. If it does throw an exception, I want to catch it and pass the exception object to a handler function. The default implementation of the handler function is simply to throw the exception. Here is whittled-down code to illustrate the issue:
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
}
}
}
However, the throw e
in exception_handler()
throws a copy of the static type of the exception, i.e., base_exception
. How can I make exception_handler()
throw the actual exception having the correct run-time type of derived_exception
? Or how can I redesign things to get what I want?
You can put a throw_me
virtual function in the base exception class, and have every derived class override it. The derived classes can throw the proper most derived type, without slicing. Even though the function has the same definition in each class, they're not the same - the type of *this
is different in each case.
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();
}
You can use throw;
to re-throw the exception that was caught. You could also use a template.
template<typename T> void rethrow(const T& t) { throw t; }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With