views:

1117

answers:

11

I've seen at least one reliable source (a C++ class I took) recommend that application-specific exception classes in C++ should inherit from std::exception. I'm not clear on the benefits of this approach.

In C# the reasons for inheriting from ApplicationException are clear: you get a handful of useful methods, properties and constructors and just have to add or override what you need. With std::exception it seems that all you get is a what() method to override, which you could just as well create yourself.

So what are the benefits, if any, of using std::exception as a base class for my application-specific exception class? Are there any good reasons not to inherit from std::exception?

+5  A: 

The reason why you might want to inherit from std::exception is because it allows you to throw an exception that is caught according to that class, ie:

class myException : public std::exception { ... };
try {
    ...
    throw myException();
}
catch (std::exception &theException) {
    ...
}
TokenMacGuy
+2  A: 

http://stackoverflow.com/questions/1569726/difference-stdruntimeerror-vs-stdexception/1569760#1569760

Whether you should inherit from it or not is up to you. Standard std::exception and its standard descendants propose one possible exception hierarchy structure (division into logic_error subhierarchy and runtime_error subhierarchy) and one possible exception object interface. If you like it - use it. If for some reason you need something different - define your own exception framework.

AndreyT
+21  A: 

The main benefit is that code using your classes doesn't have to know exact type of what you throw at it, but can just catch the std::exception.

Edit: as Martin and others noted, you actually want to derive from one of the sub-classes of std::exception declared in <stdexcept> header.

Nikolai N Fetissov
There is no way to pass a message to std::exception. std::runtime_error accepts a string and is derived from std::exception.
Martin York
+2  A: 

If all your possible exceptions derive from std::exception, your catch block can simply catch(std::exception & e) and be assured of capturing everything.

Once you've captured the exception, you can use that what method to get more information. C++ doesn't support duck-typing, so another class with a what method would require a different catch and different code to use it.

Mark Ransom
jmucchiello
Now that was a dumb mistake - certainly I know better. http://stackoverflow.com/questions/1095225/exception-slicing-is-this-due-to-generated-copy-constructor/1095233#1095233
Mark Ransom
+8  A: 

Reason for inheriting from std::exception is it "standard" base class for exceptions, so it is natural for other people on a team, for example, to expect that and catch base std::exception.

If you are looking for convenience, you can inherit from std::runtime_error that provides std::string constructor.

Aleksei Potov
+2  A: 

Since the language already throws std::exception, you need to catch it anyway to provide decent error reporting. You may as well use that same catch for all unexpected exceptions of your own. Also, almost any library that throws exceptions would derive them from std::exception.

In other words, its either

catch (...) {cout << "Unknown exception"; }

or

catch (const std::exception &e) { cout << "unexpected exception " << e.what();}

And the second option is definitely better.

Arkadiy
+6  A: 

There is one problem with inheritance that you should know about is object slicing. When you write thown e; a throw-expression initializes a temporary object, called the exception object, the type of which is determined by removing any top-level cv-qualifiers from the static type of the operand of throw. That could be not what you're expecting. Example of problem you could find here.

It is not an argument against inheritance, it is just 'must know' info.

Kirill V. Lyadvinsky
I think the take away is that "throw e;" is evil, and "throw;" is ok.
James Schek
Yes, `throw;` is ok, but it is not obvious that you should write something like this.
Kirill V. Lyadvinsky
It's especially painful for Java developers where rethrow is done using "throw e;"
James Schek
+3  A: 

You should inherit from boost::exception. It provides a lot more features and well-understood ways to carry additional data... of course, if you're not using Boost, then ignore this suggestion.

James Schek
+9  A: 

The problem with std::exception is that there is no constructor (in the standard compliant versions) that accepts a message.

As a result I prefer to derive from std::runtime_error. This is derived from std::exception but its constructors allow you to pass a C-String or a std::string to the constructor that will be returned (as a char const*) when what() is called.

Martin York
+1  A: 

I once participated in the clean up of a large codebase where the previous authors had thrown ints, HRESULTS, std::string, char*, random classes... different stuff everywhere; just name a type and it was probably thrown somewhere. And no common base class at all. Believe me, things were much tidier once we got to the point that all the thrown types had a common base we could catch and know nothing was going to get past. So please do yourself (and those who'll have to maintain your code in future) a favor and do it that way from the start.

timday
+3  A: 

Yes you should derive from std::exception.

Others have answered that std::exception has the problem that you can't pass a text message to it, however it is generally not a good idea to attempt to format a user message at the point of the throw. Instead, use the exception object to transport all relevant information to the catch site which can then format a user-friendly message.

Emil
+1, good point. Both from a separation of concerns and an i18n perspective, it's definitely better to let the presentation layer construct the user message.
John M Gant