Should I inherit from std::exception?

C++ExceptionException Handling

C++ Problem Overview


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?

C++ Solutions


Solution 1 - C++

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.

Solution 2 - C++

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.

Solution 3 - C++

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.

Solution 4 - C++

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.

Solution 5 - C++

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.

Solution 6 - C++

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.

Solution 7 - C++

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) {
    ...
}

Solution 8 - C++

There is one problem with inheritance that you should know about is object slicing. When you write throw 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.

Solution 9 - C++

https://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.

Solution 10 - C++

Whether to derive from any standard exception type or not is the first question. Doing so enables a single exception handler for all standard library exceptions and your own, but it also encourages such catch-them-all handlers. The problem is that one should only catch exceptions one knows how to handle. In main(), for example, catching all std::exceptions is likely a good thing if the what() string will be logged as a last resort before exiting. Elsewhere, however, it's unlikely to be a good idea.

Once you've decided whether to derive from a standard exception type or not, then the question is which should be the base. If your application doesn't need i18n, you might think that formatting a message at the call site is every bit as good as saving information and generating the message at the call site. The problem is that the formatted message may not be needed. Better to use a lazy message generation scheme -- perhaps with preallocated memory. Then, if the message is needed, it will be generated on access (and, possibly, cached in the exception object). Thus, if the message is generated when thrown, then a std::exception derivate, like std::runtime_error is needed as the base class. If the message is generated lazily, then std::exception is the appropriate base.

Solution 11 - C++

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.

Solution 12 - C++

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.

Solution 13 - C++

Another reason to sub-class exceptions is a better design aspect when working on large encapsulated systems. You can reuse it for things such as validation messages, user queries, fatal controller errors and so on. Rather than rewriting or rehooking all of your validation like messages you can simply "catch" it on the main source file, but throw the error anywhere in your entire set of classes.

e.g. A fatal exception will terminate the program, a validation error will only clear the stack and a user query will ask the end-user a question.

Doing it this way also means you can reuse the same classes but on different interfaces. e.g. A windows application can use message box, a web service will show html and reporting system will log it and so on.

Solution 14 - C++

Though this question is rather old and has already been answered plenty, I just want to add a note on how to do proper exception handling in C++11, since I am continually missing this in discussions about exceptions:

Use std::nested_exception and std::throw_with_nested

It is described on StackOverflow here and here, how you can get a backtrace on your exceptions inside your code without need for a debugger or cumbersome logging, by simply writing a proper exception handler which will rethrow nested exceptions.

Since you can do this with any derived exception class, you can add a lot of information to such a backtrace! You may also take a look at my MWE on GitHub, where a backtrace would look something like this:

Library API: Exception caught in function 'api_function'
Backtrace:
~/Git/mwe-cpp-exception/src/detail/Library.cpp:17 : library_function failed
~/Git/mwe-cpp-exception/src/detail/Library.cpp:13 : could not open file "nonexistent.txt"
You don't even need to subclass std::runtime_error in order to get plenty of information when an exception is thrown.

The only benefit I see in subclassing (instead of just using std::runtime_error) is that your exception handler can catch your custom exception and do something special. For example:

try
{
  // something that may throw
}
catch( const MyException & ex )
{
  // do something specialized with the
  // additional info inside MyException
}
catch( const std::exception & ex )
{
  std::cerr << ex.what() << std::endl;
}
catch( ... )
{
  std::cerr << "unknown exception!" << std::endl;
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJohn M GantView Question on Stackoverflow
Solution 1 - C++Nikolai FetissovView Answer on Stackoverflow
Solution 2 - C++Martin YorkView Answer on Stackoverflow
Solution 3 - C++Aleksei PotovView Answer on Stackoverflow
Solution 4 - C++timdayView Answer on Stackoverflow
Solution 5 - C++James SchekView Answer on Stackoverflow
Solution 6 - C++EmilView Answer on Stackoverflow
Solution 7 - C++SingleNegationEliminationView Answer on Stackoverflow
Solution 8 - C++Kirill V. LyadvinskyView Answer on Stackoverflow
Solution 9 - C++AnTView Answer on Stackoverflow
Solution 10 - C++RobView Answer on Stackoverflow
Solution 11 - C++Mark RansomView Answer on Stackoverflow
Solution 12 - C++user3458View Answer on Stackoverflow
Solution 13 - C++James BurnbyView Answer on Stackoverflow
Solution 14 - C++GPMuellerView Answer on Stackoverflow