Login

Username:

Password: 

Join us Now |  Forgot Password? | Forgot UserName?

C++

Learn step by step



Exceptions

During development of a program, there may be some cases where we don't 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 incompatible situations are included in what we consider exceptions and C++ has recently incorporated 3 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 that executed in case of exception
}

An exception is a problem that arises during the execution of a program. C++ exception is a response to an exceptional circumstance that arises while a program is running, such as an attempt to divide by 0.

  • throw: Program throws an exception when a problem shows up. This is done using the keyword throw.
  • catch: Program catches an exception with an exception handler at the place in a program where we want to handle the problem. The keyword catch indicates the catching of an exception.
  • try: Try block identifies a block of code for which particular exceptions will be activated. It is followed by one or more catch blocks.


// 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;
}

Output


Exception: Out of range

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

Syntax used by throw is similar to return: Only the parameter doesn't need to be enclosed between parenthesis.

The catch block must go right after the try block without including any code line between them. Parameter that catch accepts can be of any valid type. Even, catch can be overloaded so that it can accept different types as parameters. In that case 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;
}

Output

Exception: index 10 is out of range

Throwing Exceptions:

Exceptions can be thrown anywhere within a code block using throw statements. Operand of the throw statements determines a type for the exception and can be any expression and the type of the result of the expression determines the type of exception thrown.

Following is a example of throwing an exception when dividing by zero condition occurs:

double division(int a, int b)
{
if( b == 0 )
{
throw "Division by zero condition!";
}
return (a/b);
}

Catching Exceptions:

The catch block following the try block catches any exception. We can specify what type of exception you want to catch and this is determined by the exception declaration that appears in parentheses following the keyword catch.

try
{
// protected code
}catch( ExceptionName e )
{
// code to handle exception- ExceptionName
}

Above code will catch an exception of ExceptionName type. If we want to specify that a catch block should handle any type of exception that is thrown in a try block, we must put an ellipsis, ..., between parentheses enclosing the exception declaration as follows:

try
{
// protected code
}catch(...)
{
// code to handle any exception
}

Following is a example, which throws a division by 0 exception and we catch it in catch block.


#include <iostream>
using namespace std;

double division(int a, int b)
{
if( b == 0 )
{
throw "Division by zero condition!";
}
return (a/b);
}

int main ()
{
int x = 50;
int y = 0;
double z = 0;

try {
z = division(x, y);
cout << z << endl;
}catch (const char* msg) {
cerr << msg << endl;
}

return 0;
}

Because we are raising an exception of type const char*, so while catching this exception, we have to use const char* in catch block. If we compile and run above code, this would produce the following result:

Output

Division by zero condition!

Standard exceptions

C++ Standard library provides a base class specifically designed to declare objects to be thrown as exceptions. It's called std::exception and is defined in the header. This 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.


// 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;
}

Output

My exception happened.

We have placed an 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 C++ Standard library throw exceptions derived from this exception class:



exceptiondescription
bad_allocthrown by the new on allocation failure
bad_castthrown by dynamic_cast when it fails in a dynamic cast
bad_exceptionthrown by certain dynamic exception specifiers
bad_typeidthrown by typeid
bad_function_callthrown by empty function objects
bad_weak_ptrthrown 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:

exceptiondescription
logic_errorerror related to the internal logic of the program
runtime_errorerror detected during runtime

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


// 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;
}

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



Related Videos