C++ Exceptions

Exceptions are exceptional conditions. Exception handling manages situations that otherwise would make the system crash or misbehave. Exceptions are classes that are thown or returned from code inside a try block to be dealt in a catch block.

This is the basic structure of exception handling for handling a generic object of class exception:

#include <exception>

try {
  // ...
  throw exception(); // construct and exception object
  // ...
} catch (exception & ex) {
  cout << "exception bearing message: \"" << ex.what() << "\" has been thrown..." << endl;
} // code resumes here

Class std::exception

Class exception is declared in <exception>. It cannot be initialized with a string message. Thus, to handle an exception in a catch clause, you may use the exception interface. The interface of all standard exceptions classes contains only one member that can be used to get additional information besides the type itself: the member function what(), which returns a null-terminated byte string. The content of the string is implementation defined. The C-string, returned by what(), is valid until the exception object from which it is obtained gets destroyed.

#include <exception>
class exception { // since C++11
                  // all member functions are constexpr
                  // since C++26
public:
  exception& operator=(const exception& other) noexcept; // since C++11
                                                                            // constexpr since C++26
  virtual const char* what()                                const noexcept; //
                                                                            // constexpr since C++26
  exception() noexcept;
  exception(const exception& other) noexcept;
};

(The remaining members of the standard exception classes create, copy, assign, and destroy exception objects. Note that besides what() there is no additional member for any of the standard exception classes that describes the kind of exception. For example, there is no portable way to find out the context of an exception or the faulty index of a range error. Thus, a portable evaluation of an exception could only print the message returned from, well, what().)

Exception Action

An exception thrown transfers control to the first matching catch block after all objects constructed in the try block have been deleted.

The exception classes

These are the exception classes, derived from class exception:

Header Files for Exception Classes

The base class exception and class bad_exception are defined in <exception>. Class bad_alloc is defined in <new>. Classes bad_cast and bad_typeid are defined in <typeinfo>. Class ios_base::failure is defined in <ios>. All other classes are defined in <stdexcept>.

Writing Your Own Exception Classes

To write an exception class, you should:

  1. Derive your class from std::exception or some other STL exception class, as in

    class my_exception_class : public std::exception {...
  2. override the virtual const char* what() const noexcept method in std::exception

  3. Optionally add some features such as initializing with a string or printing detailed information, as explained in the following subsections.

Writing Exception Classes that Initialize with a String

Just add a non-public const string member and a constructor that takes a string:

#include <exception>
class string_initializable_exception : public std::exception {
  const std::string str;
public:
  const char* what() const noexcept override {
    return str.c_str();
  };
  string_initializable_exception(const char * txt) : str(txt) {};
};

Note Quite probably you don't want to provide a default constructor, though.

Writing Exception Classes that Build a Formated String through an std::sstream

You want to code an exception whose error message is as rich in information as possible by incorporating input parameters into the string that member what() outputs.

In all the examples in this subsection, std::stringstream ss is built with parameters (in the constructor's body), then assigned to member std::string s, wherefrom a C-string is extracted.

Yes, you might build your exception message outside your exception object and then initialize an string_initializable_exception object with that string. But let us assume you aim for something more automatic. You want to build the error message inside your exception object.

Now, since initialization is complex, member string s must not be marked as const as the message string needs to be built in stages inside the constructor's body, as already explained.


I shall first illustrate a simple class that takes one integer parameter, x:

#include <exception>
#include <sstream>

class x_exception : public std::exception {
  std::string        s;
  std::stringstream ss;
public:
  const char* what() const noexcept override {
    return s.c_str();
  };
  x_exception() = delete;
  x_exception(int x) : s("x=") {
    ss << x;
    s += ss.str();
  };
};

Here, std::stringstream ss is used for converting a number to a string.


The next example is more sophisticated and allows for more complexity.

Also, two parameters of deducible types X and Y are read:

...
...

Order of catch blocks

Catch blocks for exceptions by reference will also latch onto derived exception classes, so it is advisable to place the most specific catch blocks at the start.

Lastly, all exceptions is selected for as catch (...). Here is an example. Assume that derived_exception is derived from exception, and that there are other exceptions not derived from exception:

#include <exception>

try {
  // exception-throwing code
} catch (derived_exception & dex) {
  // code handling derived_exception
} catch (exception & dex) {
  // code handling exception objects and derived objects
} catch (...) {
  // code handling all remaining exceptions
}
// code resumes here

Exception specification

A function may be declared to throw only one or several classes of exceptions:

voide f() throw (excpt1, excpt2);

Then, if f() throws a different exception, global unexpected() is called.

An empty specification list means that no exception may be thrown.

Exception specifications help other developers understand how your code works and behaves.