Section 5.3
Exception handling
cplusplus.com

Exception handling explained in this section is a new feature introduced by ANSI-C++ standard. If you use a C++ compiler that is not adapted to this standard it is possible that you cannot use this feature.

During the development of a program, there may be some cases where we do not have the certainty that a piece of the code is going to work right, either because it accesses resources that do not exist or because it gets out of an expected range, etc...

These types of anomalous situations are included in what we consider exceptions and C++ has recently incorporated three new operators to help us handle these situations: try, throw and catch.

Their form of use is the following:

try {
  // code to be tried
  throw exception;
}
catch (type  exception)
{
  // code to be executed in case of exception
}
And its operation:
- The code within the try block is executed normally. In case that an exception takes place, this code must use the throw keyword and a parameter to throw an exception. The type of the parameter details the exception and can be of any valid type.
- If an exception has taken place, that is to say, if it has executed a throw instruction within the try block, the catch block is executed receiving as parameter the exception passed by throw.

For example:

// exceptions
#include <iostream.h>

int main () {
  char myarray[10];
  try
  {
    for (int n=0; n<=10; n++)
    {
      if (n>9) throw "Out of range";
      myarray[n]='z';
    }
  }
  catch (char * str)
  {
    cout << "Exception: " << str << endl;
  }
  return 0;
}
Exception: Out of range

In this example, if within the n loop, n gets to be more than 9 an exception is thrown, since myarray[n] would in that case point to a non-trustworthy memory address. When throw is executed, the try block finalizes right away and every object created within the try block is destroyed. After that, the control is passed to the corresponding catch block (that is only executed in these cases). Finally the program continues right after the catch block, in this case: return 0;.

The syntax used by throw is similar to that of return: Only the parameter does not need to be enclosed between parenthesis.

The catch block must go right after the try block without including any code line between them. The parameter that catch accepts can be of any valid type. Even more, catch can be overloaded so that it can accept different types as parameters. In that case the catch block executed is the one that matches the type of the exception sent (the parameter of throw):

// exceptions: multiple catch blocks
#include <iostream.h>

int main () {
  try
  {
    char * mystring;
    mystring = new char [10];
    if (mystring == NULL) throw "Allocation failure";
    for (int n=0; n<=100; n++)
    {
      if (n>9) throw n;
      mystring[n]='z';
    }
  }
  catch (int i)
  {
    cout << "Exception: ";
    cout << "index " << i << " is out of range" << endl;
  }
  catch (char * str)
  {
    cout << "Exception: " << str << endl;
  }
  return 0;
}
Exception: index 10 is out of range

In this case there is a possibility that at least two different exceptions could happen:

  1. That the required block of 10 characters cannot be assigned (something rare, but possible): in this case an exception is thrown that will be caught by catch (char * str).
  2. That the maximum index for mystring is exceeded: in this case the exception thrown will be caught by catch (int i), since the parameter is an integer number.

We can also define a catch block that captures all the exceptions independently of the type used in the call to throw. For that we have to write three points instead of the parameter type and name accepted by catch:

try {
  // code here
}
catch (...) {
  cout << "Exception occurred";
}

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 received to the external level, for that the expression throw; with no arguments is used. For example:

try {
  try {
      // code here
  }
  catch (int n) {
      throw;
  }
}
catch (...) {
  cout << "Exception occurred";
}

Exceptions not caught

If an exception is not caught by any catch statement because there is no catch statement with a matching type, the special function terminate will be called.

This function is generally defined so that it terminates the current process immediately showing an "Abnormal termination" error message. Its format is:

void terminate();

Standard exceptions

Some functions of the standard C++ language library send exceptions that can be captured if we include them within a try block. These exceptions are sent with a class derived from std::exception as type. This class (std::exception) is defined in the C++ standard header file <exception> and serves as a pattern for the standard hierarchy of exceptions:
exception
bad_alloc(thrown by new)
bad_cast(thrown by dynamic_cast when fails with a referenced type)
bad_exception(thrown when an exception doesn't match any catch)
bad_typeid(thrown by typeid)
logic_error
domain_error
invalid_argument
length_error
out_of_range
runtime_error
overflow_error
range_error
underflow_error
ios_base::failure(thrown by ios::clear)
Because this is a class hierarchy, if you include a catch block to capture any of the exceptions of this hierarchy using the argument by reference (i.e. adding an ampersand & after the type) you will also capture all the derived ones (rules of inheritance in C++).

The following example catches an exception of type bad_typeid (derived from exception) that is generated when requesting information about the type pointed by a null pointer:

// standard exceptions

#include <iostream.h>
#include <exception>
#include <typeinfo>

class A {virtual f() {}; };

int main () {
  try {
    A * a = NULL;
    typeid (*a);
  }
  catch (std::exception& e)
  {
    cout << "Exception: " << e.what();
  }
  return 0;
}
Exception: Attempted typeid of NULL pointer

You can use the classes of standard hierarchy of exceptions to throw your exceptions or derive new classes from them.

© The C++ Resources Network, 2000-2003 - All rights reserved

Previous:
5-2. Namespaces.

index
Next:
5-4. Advanced classes type-cast.