I am designing an exception hierarchy in C++ for my library. The “hierarchy” is 4 classes derived from std::runtime_error. I would like to avoid the slicing problem for the exception classes so made the copy constructors protected. But apparently gcc requires to call the copy constructor when throwing instances of them, so complains about the protected copy constructors. Visual C++ 8.0 compiles the same code fine. Are there any portable way to defuse the slicing problem for exception classes? Does the standard say anything about whether an implementation could/should require copy constructor of a class which is to be thrown?
Share
I would steer clear of designing an exception hierarchy distinct to your library. Use the
std::exceptionhierarchy as much as possible and always derive your exceptions from something within that hierarchy. You might want to read the exceptions portion of Marshall Cline’s C++ FAQ – read FAQ 17.6, 17.9, 17.10, and 17.12 in particular.As for "forcing users to catch by reference", I don’t know of a good way of doing it. The only way that I have come up with in an hour or so of playing (it is Sunday afternoon) is based on polymorphic throwing:
The idea is to make the copy constructor protected and force users to call
Class(args).raise()instead ofthrow Class(args). This lets you throw a polymorphicly bound exception that your users can only catch by reference. Any attempt to catch by value should be greeted with a nice compiler warning. Something like:Of course this all comes at a price since you can no longer use
throwexplicitly or you will be greeted with a similar compiler warning:Overall, I would rely on coding standards and documentation stating the you should always catch by reference. Make sure that your library catches exceptions that it handles by reference and throw fresh objects (e.g.,
throw Class(constructorArgs)orthrow;). I would expect other C++ programmers to have the same knowledge – but add a note to any documentation just to be sure.