Which of the following two catch
blocks is easier to understand:
try {
do_something();
}
catch (const int&) {
// WTF did I catch?
}
catch (const std::out_of_range&) {
// Oh, something was out of range!
}
The name of an exception class should tell you something about why the exception was thrown; int
doesn't tell you anything, you just know that you caught an int
, whatever that means.
To consider your updated example of using an enumeration instead of an integer, which of the following is clearer:
try{
do_something();
}
// (1) Catch an enum:
catch (MyException e) {
switch(e) {
except_a: break;
except_b: break;
except_c: break;
default: throw; // Don't forget, you have to throw any exceptions
// that you caught but don't actually want to catch!
}
}
// (2) Catch specific exceptions
catch (const ExceptionA&) { }
catch (const ExceptionB&) { }
catch (const ExceptionC&) { }
There is no reason at all to prefer the first form: there's no performance benefit and the code is less clear and more error-prone. In your example, you forgot to rethrow the exception if you weren't handling it, so if someone later added an except_d
exception to the MyException
enumeration, you'd have unknowingly caught it.
As for your "overhead" question, it depends, but probably not. It should be (relatively) rare that an exception is thrown, and if you have a tight loop where performance really matters, you aren't going to be using exceptions anyway.
The benefit of using class hierarchies for exceptions is that they allow you to write clearer code, just like the benefit of using non-local control flow (exceptions) instead of other approaches like error code return values allows you to write clearer code (at least when you use exceptions correctly).