Always catch exceptions by reference

Some code I am responsible for at work recently got exposed to a new environment, and suddenly started logging exceptions. After some investigation, my colleague Thomas and I felt pretty sure what was going on, except the exception we saw in the logs was of a different type than the one that was thrown by the suspected culprit. What was going on, could the error be some place else after all? Then we looked at some intermediate code in the call hierarchy, and found the following (as usual, simplified) code :

class Exception{};
class SpecialException : public Exception {};

try {
    throw SpecialException();
} catch (Exception e) {
    cout << "Caught" << typeid(e).name() << endl;

Spot the problem? catch (Exception e) results in slicing. We are catching by value, which results in copying the exception. But since we are catching Exception, not SpecialException, Exception‘s copy construcor is called, and we lose the SpecialException part of the object. Here is an illustration of the Exception copy constructor in action:

Exception copy constructor slices away the SpecialException part of the object

On the left side is the full SpecialException object, with its Exception part shown in green. The green line illustrates the copy constructor, which only lets the Exception part of the object throuh.

The right way to write this would be catch (const Exception& e), which would result in a reference to the original SpecialException. Thanks to polymorphism, this program will now print “Caught SpecialException”, whereas the original example prints “Caught Exception”.

As a side note, always throw by value, not by pointer. That is, do throw Exception();, not throw new Exception();. After all, you want to be throwing an exception, not a pointer. And as always, there is no point in allocating on the heap if you don’t have to. Requiring people to clean up memory for you when catching is not very polite.