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.