According to the C++ FAQ, when one throws an object, it's thrown using the static type of the expression. Hence, if you have:
catch ( some_exception const &e ) {
// ...
throw e; // throws static type, possibly causing "slicing"; should just "throw;" instead
}
and e
is actually a reference to some class derived from some_exception
, the above throw
will cause the object to be "sliced" silently. Yes, I know the correct answer is simply to throw;
, but the way things are seems like an unnecessary source of confusion and bugs.
What's the rationale for this? Why wouldn't you want it to throw by the dynamic type of the object?
When you throw
something, a temporary object is constructed from the operand of the throw
and that temporary object is the object that is caught.
C++ doesn't have built-in support for copying things or creating objects based on the dynamic type of an expression, so the temporary object is of the static type of the operand.
The "argument" to throw
is an expression and it is the type of the expression that determines the type of the exception object thrown. The type of the expression thrown doesn't necessarily have to be a polymorphic type so there may not be a way to determine if the expression actually refers to a base class subobject of a more derived type.
The simpler "type of the expression" rule also means that the implementation doesn't have to dynamically determine the size and type of the exception object at runtime which might require more complex and less efficient code to be generated for exception handling. If it had to do this it would represent the only place in a language where a copy constructor for a type unknown at the call point was required. This might add significantly to the cost of implementation.
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