try
{
throw Derived();
}
catch (Base&)
{
std::cout << "subtyping\n";
}
try
{
throw "lol";
}
catch (std::string)
{
std::cout << "coercion\n";
}
Output:
subtyping
terminate called after throwing an instance of 'char const*'
Why does exception handling play nice with subtyping, but not with coercion?
Catching thrown exceptions is quite different from passing arguments to functions. There are similarities, but there are also subtle differences.
The 3 main differences are:
catch
clauses are examined in the order they are declared (not best-fit)const void*
catches any pointer)Any other kind of conversion is not allowed (e.g. int
to double
, or implicit const char*
to string
- your example).
Regarding your question in the comment Suppose a hierarchy exists:
class Base {};
class Derived: public Base {};
class Base2 {};
class Leaf: public Derived, public Base2 {};
Now depending on the order of catch
clauses, an appropriate block will be executed.
try {
cout << "Trying ..." << endl;
throw Leaf();
} catch (Base& b) {
cout << "In Base&";
} catch (Base2& m) {
cout << "In Base2&"; //unreachable due to Base&
} catch (Derived& d) {
cout << "In Derived&"; // unreachable due to Base& and Base2&
}
If you switch Base
and Base2
catch order you will notice a different behavior.
If Leaf
inherited privately from Base2
, then catch Base2&
would be unreachable no matter where placed (assuming we throw a Leaf
)
Generally it's simple: order matters.
Paragraph 15.3/3 of the C++11 Standard defines the exact conditions for a handler to be a match for a certain exception object, and these do not allow user-defined conversions:
A handler is a match for an exception object of type
E
if— The handler is of type
cv T
orcv T&
andE
andT
are the same type (ignoring the top-levelcv
-qualifiers), or— the handler is of type
cv T
orcv T&
andT
is an unambiguous public base class ofE
, or— the handler is of type
cv1 T* cv2
andE
is a pointer type that can be converted to the type of the handler by either or both of
a standard pointer conversion (4.10) not involving conversions to pointers to private or protected or ambiguous classes
a qualification conversion
— the handler is a pointer or pointer to member type and
E
isstd::nullptr_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