Search:

- Tutorials
- C++ Language
- Exceptions

Not logged in
register log in
user name:
password:
remember me
forgot your password?
or sign in using:
try again cancel
forgot your password?

# Exceptions

Exceptions provide a way to react to exceptional circumstances (like runtime errors) in programs by transferring control to special functions called handlers.
To catch exceptions, a portion of code is placed under exception inspection. This is done by enclosing that portion of code in a try-block. When an exceptional circumstance arises within that block, an exception is thrown that transfers the control to the exception handler. If no exception is thrown, the code continues normally and all handlers are ignored.
An exception is thrown by using the `throw` keyword from inside the `try` block. Exception handlers are declared with the keyword `catch`, which must be placed immediately after the `try` block:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    // exceptions
    #include <iostream>
    using namespace std;

    int main () {
      try
      {
        throw 20;
      }
      catch (int e)
      {
        cout << "An exception occurred. Exception Nr. " << e << '\n';
      }
      return 0;
    }
    An exception occurred. Exception Nr. 20
| Edit & Run

The code under exception handling is enclosed in a `try` block. In this example this code simply throws an exception:

    throw 20;

A `throw` expression accepts one parameter (in this case the integer value `20`), which is passed as an argument to the exception handler.
The exception handler is declared with the `catch` keyword immediately after the closing brace of the `try` block. The syntax for `catch` is similar to a regular function with one parameter. The type of this parameter is very important, since the type of the argument passed by the `throw` expression is checked against it, and only in the case they match, the exception is caught by that handler.
Multiple handlers (i.e., `catch` expressions) can be chained; each one with a different parameter type. Only the handler whose argument type matches the type of the exception specified in the `throw` statement is executed.
If an ellipsis (`...`) is used as the parameter of `catch`, that handler will catch any exception no matter what the type of the exception thrown. This can be used as a default handler that catches all exceptions not caught by other handlers:

    1
    2
    3
    4
    5
    6
    try {
      // code here
    }
    catch (int param) { cout << "int exception"; }
    catch (char param) { cout << "char exception"; }
    catch (...) { cout << "default exception"; }

In this case, the last handler would catch any exception thrown of a type that is neither `int` nor `char`.
After an exception has been handled the program, execution resumes after the try-catch block, not after the `throw` statement!.
It is also possible to nest `try-catch` blocks within more external `try` blocks. In these cases, we have the possibility that an internal `catch` block forwards the exception to its external level. This is done with the expression `throw;` with no arguments. For example:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    try {
      try {
          // code here
      }
      catch (int n) {
          throw;
      }
    }
    catch (...) {
      cout << "Exception occurred";
    }

### Exception specification

Older code may contain dynamic exception specifications. They are now deprecated in C++, but still supported. A dynamic exception specification follows the declaration of a function, appending a `throw` specifier to it. For example:

    double myfunction (char param) throw (int);

This declares a function called `myfunction`, which takes one argument of type `char` and returns a value of type `double`. If this function throws an exception of some type other than `int`, the function calls `std::unexpected` instead of looking for a handler or calling `std::terminate`.
If this `throw` specifier is left empty with no type, this means that `std::unexpected` is called for any exception. Functions with no `throw` specifier (regular functions) never call `std::unexpected`, but follow the normal path of looking for their exception handler.

    1
    2
    int myfunction (int param) throw(); // all exceptions call unexpected
    int myfunction (int param);         // normal exception handling

### Standard exceptions

The C++ Standard library provides a base class specifically designed to declare objects to be thrown as exceptions. It is called `std::exception` and is defined in the `<exception>` header. This class has a virtual member function called `what` that returns a null-terminated character sequence (of type `char *`) and that can be overwritten in derived classes to contain some sort of description of the exception.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    // using standard exceptions
    #include <iostream>
    #include <exception>
    using namespace std;

    class myexception: public exception
    {
      virtual const char* what() const throw()
      {
        return "My exception happened";
      }
    } myex;

    int main () {
      try
      {
        throw myex;
      }
      catch (exception& e)
      {
        cout << e.what() << '\n';
      }
      return 0;
    }
    My exception happened.
| Edit & Run

We have placed a handler that catches exception objects by reference (notice the ampersand `&` after the type), therefore this catches also classes derived from `exception`, like our `myex` object of type `myexception`.
All exceptions thrown by components of the C++ Standard library throw exceptions derived from this `exception` class. These are:

exception | description
--- | ---
`bad_alloc` | thrown by `new` on allocation failure
`bad_cast` | thrown by `dynamic_cast` when it fails in a dynamic cast
`bad_exception` | thrown by certain dynamic exception specifiers
`bad_typeid` | thrown by `typeid`
`bad_function_call` | thrown by empty `function` objects
`bad_weak_ptr` | thrown by `shared_ptr` when passed a bad `weak_ptr`

Also deriving from `exception`, header `<exception>` defines two generic exception types that can be inherited by custom exceptions to report errors:

exception | description
--- | ---
`logic_error` | error related to the internal logic of the program
`runtime_error` | error detected during runtime

A typical example where standard exceptions need to be checked for is on memory allocation:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    // bad_alloc standard exception
    #include <iostream>
    #include <exception>
    using namespace std;

    int main () {
      try
      {
        int* myarray= new int[1000];
      }
      catch (exception& e)
      {
        cout << "Standard exception: " << e.what() << endl;
      }
      return 0;
    }
| Edit & Run

The exception that may be caught by the exception handler in this example is a `bad_alloc`. Because `bad_alloc` is derived from the standard base class `exception`, it can be caught (capturing by reference, captures all related classes).

Previous: Type conversions | Index | Next: Preprocessor directives