Exception Handling in C++

What is an exception?

Exception is an event that happens when unexpected circumstances appear. It can be a runtime error or you can create an exceptional situation programmatically.

Exception handling consists in transferring control from the place where exception happened to the special functions (commands) called handlers.

How to handle exceptions?

Exceptions are handled by using try/catch block. The code that can produce an exception is surrounded with try block. The handler for this exception is placed in catch block:

Try/catch block uses the following syntax:

try
{
	//code that can produce error
}
catch (ExceptionType e)
{
	//exception handler 
}

Example of an exception:

Look on the following example:

//use a vector
vector<int> arr;

//push two elements into vector
arr.push_back(4);
arr.push_back(7);

//try to access the third element that does not exist
arr.at(2);

This code compiles without errors.  Nevertheless, if you try to run this program, you will get an error:

 

You are trying to access an element of a vector that does not exist. at(int) member function of vector throws exception when it is called.

Example of exception handling.

You can re-write this program using exception-handling mechanism:

//use a vector
vector<int> arr;

//push two elements into vector
arr.push_back(4);
arr.push_back(7);

//try to access the third element that does not exist
try
{
	arr.at(2);
}
catch (...)//catch all exceptions
{
	cout << "Exception happened" << endl;
}

As you can see, exception handling makes your code safer and protects your program from runtime errors.

Built-in exceptions

C++ provides a range of built in exceptions. The base class for all exceptions classes is exception

The information about happened exception is provided by what() member function of  the exception class:

//try to access the third element that does not exist
try
{
	arr.at(2);
}
catch (exception& e)//catch all exceptions
{
	cout << "Exception happened: " << e.what() << endl;
}

In this case, you will get following output:

Exception happened: invalid vector<T> subscript

All the Standard Exceptions are listed in the following diagram:

Short description of these exceptions is provided in these tables:

Exceptions derived directly from exception class:

 bad_alloc

 Happens when there is a failure of memory allocation

 bad_cast

 Is thrown when dynamic_cast is used incorrect

 bad_exception

 Exception that is thrown by unexpected handler

 bad_function_call

 Thrown when an empty (not implemented) function is called

 bad_typeid

 Thrown by typeid function

 bad_weak_ptr

 Exception that can be thrown by shared_ptr class constructor

 ios_base::failure

 Base class for all the stream exceptions

 logic_error

 Base class for some logic error exceptions

 runtime_error

 Base class for some runtime error exceptions

 

Exceptions derived indirectly from exception class through logic_error:

 domain_error

 Thrown when an error of function domain happens

 future_error

 Reports an exception that can happen in future objects(See more info about future class)

 invalid_argument

 Exception is thrown when invalid argument is passed

 length_error

 Is thrown when incorrect length is set

 out_of range error

 Is thrown when out of range index is used

 

Exceptions derived indirectly from exception class through runtime_error:

 overflow_error

 Arithmetic overflow exception

 range_error

 Signals range error in computations

 system_error

 Reports an exception from operating system

 underflow_error

 Arithmetic underflow exceptions

 

How to throw an exception

There is a possibility to throw an exception. It can be done by using throw keyword.

Look on example:

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

Function divide throws an exception in form of string, when denominator is zero. In this case, the execution of function is terminated and exception is thrown to the place where function was called. Now, try to call this function with incorrect parameter:

try
{
	double res = divide(1, 0);
}
catch (char* c)
{
	cout << c;
}

This produces the following output:

Division by zero

How to extend exception class?

Sometimes, you will need to create your own exception classes. This can be done for different purposes. For example, you want to send some information from the place, where exception happened, to the catch block. It can be done by extending class exception. In this case, you can create a constructor for the derived class and override its member function what().

class ZeroDivisionException :public exception
{
public:
	ZeroDivisionException(int data)
	{
		someData = data;
	}
	//override what function
	const char* what()
	{
		return "Zero division error";
	}
	int someData;
};

ZeroDivisionException class stores an integer data member someData. Now we can get the information from the place, where exception happened, in the catch block. For this purpose, we will re-write divide function:

double divide(double a, double b)
{
	if (b == 0) //division by zero!!!!
		throw ZeroDivisionException(a);
	else
		return a/b;
}

Parameter a is passed and returned back from the function. We can use it in catch block:

try
{
	double res = divide(1, 0);
}
catch (ZeroDivisionException e)
{
	cout << e.what() << endl;
	cout << "Trying to divide " << e.someData << " by zero" << endl;
}

The output is

Zero division error

Trying to divide 1 by zero

Exceptions provide a powerful and efficient mechanism to control errors and make your programs safer.


Next > < Prev
Scroll to Top