C++ Exception Handling Basics Guide
C++ Exception Handling Basics Guide
BLOCK - V
EXCEPTION HANDLING
NOTES
UNIT 13 EXCEPTION HANDLING
Structure
13.0 Introduction
13.1 Objectives
13.2 Basics and Mechanism of Exception Handling
13.3 Throw Statement
13.4 Catching Mechanism
13.5 Answers to Check Your Progress Questions
13.6 Summary
13.7 Key Words
13.8 Self Assessment Questions and Exercises
13.9 Further Readings
13.0 INTRODUCTION
13.1 OBJECTIVES
After going through this unit, you will be able to:
Understand the fundamentals of exception handling
Explain about throw statement and its use
Exception handling in base and derived classes
The C++ exception handling mechanism mainly uses three keywords, try, throw
and catch. A set of statements that needs to be monitored for the exceptions is
Self-Instructional
Material 247
Exception Handling contained in the try block. The try block is surrounded by curly braces and prefixed
by the keyword try. Whenever an exception occurs within the try block, it is
thrown using the throw statement. This passes the control to the catch block,
which handles the exception appropriately (as shown in Figure 13.1). The throw
NOTES statement and the catch block are prefixed by the keywords throw and catch,
respectively.
try block
{
detects and
throws the exception
object exception
} object
passes
catch block to catch
{ block
handles the exception
appropriately
}
The catch block is also called the exception handler and it must immediately follow
the try block that throws an exception. The syntax for defining try-throw-catch
block is as follows:
...
try //try block
{
...
throw exception; //throw statement
...
}//end of try block
catch (data_type parameter) //catch block
{
...
}//end of catch block
Note: The catch block must always immediately follow the try block
irrespective of the location of the throw point.
The exception thrown using the throw statement is the object that transmits the
information about the exception. This object is known as exception object (see
Figure 13.1). Once an exception is thrown, the control is automatically transferred
to the catch block and the try block is terminated. If the data type of the exception
object matches with the data type of the parameter specified in the catch block,
the catch block is executed. If an appropriate match is not found, the standard
library function terminate() is invoked, which by default calls the abort()
function to terminate the program abnormally. However, it is not necessary that
every time the program is executed, an exception occurs. If an exception does not
Self-Instructional
248 Material
occur, the catch block is skipped and the control passes to the statement immediately Exception Handling
Self-Instructional
Material 249
Exception Handling In addition to main(), the try block can also be placed in any other user-
defined function. In this case, the try block is localized to the function in which it is
defined.
Example 13.2: A program to demonstrate the concept of defining a try block
NOTES
inside a user-defined function
#include<iostream>
using namespace std;
void sum(int n)
{
static int sum=0;
try //local try block
{
if (n>0)
{sum+=n;}
else throw(n);
}
catch(int i)
{
cout<<“Exception- negative number\n”;
cout<<“\nSum of positive numbers is: “<<sum;
}
}
int main()
{
int a;
cout<<“Enter the numbers:\n”;
do
{
cin>>a;
sum(a); //calling the function containing try block
}while(a>0);
return 0;
}
funcl()
{ control passes to
throw exception //throw point funcl()
}
throw
exception try block
{
call to funcl()
}
catch block
{
handles the exception
}
The syntax for throwing an exception from a function defined outside the try
block is as follows:
return_type func1(parameter_list)//function throwing an
exception
{
...
Self-Instructional
Material 251
Exception Handling throw(exception);
...
}
...
NOTES
try //try block
{
...
//call to func1()
...
}//end of try block
catch (data_type parameter) //catch block
{
...
}//end of catch block
void square_root(int x)
{
if (x>=0)
cout<<“Square root of the number is: “<<sqrt(x)<<endl;
else
throw(x);//throwing an exception outside the try block
}
int main()
{
int a;
cout<<“Enter any number: “;
cin>>a;
try
{
square_root(a); //calling the function, which throws
//the exception
}
catch(int i)
{
Self-Instructional
252 Material
cout<<“Exception-a negative number”; Exception Handling
}
return 0;
}
NOTES
The output of the program is
First run
Enter any number: 64
Square root of the number is: 8
Second run
Enter any number: -23
Exception-a negative number
In this example, a number entered by the user is checked for an exception. If the
user enters a positive number, the square root of the number is displayed. Otherwise,
an exception is thrown and the catch block is executed.
Note that if the function containing the throw statement is called more than
once in the try block, the function call is executed as long as no exception occurs.
Once the exception is thrown by the called function and the catch block is executed,
subsequent calls to the function will not be executed. To understand this concept,
consider the following code fragment:
...
try
{
square_root(5);
square_root(-5);
square_root(-6);
}
...
In this code fragment, the function square_root()(defined in Example 13.3)
is called three times. Since the exception is thrown in the second function call, the
third function call will not be executed. Thus, the output of the program is as
follows:
Square root of the number is: 2.23607
Exception-a negative number
This problem can be resolved by defining the try/catch block inside the function.
In this case, each time the function is called, the exception handler is reset and
invoked. For example, the try/catch block defined in Example 13.3 can be made
local to the function as given in the following code fragment:
...
void square_root(int x)
{
Self-Instructional
Material 253
Exception Handling try //local try block
{
if (x>=0)
cout<<“Square root of the number is: “<<sqrt(x);
NOTES
else
throw(x);
}
catch(int i)
{
cout<<“\nException-a negative number”;
}
}
int main()
{
...
square_root(5);
square_root(-5);
square_root(-6);
...
}
The output of the program is
Square root of the number is: 2.23607
Exception-a negative number
Exception-a negative number
In this example, since the try/catch is local to the function, all the function calls are
executed.
Self-Instructional
254 Material
{ Exception Handling
cout<<“Exception-Number is greater than 10”;
}
However, if the name of the argument is specified, then that argument can be used
NOTES
in the catch block. To understand this concept, consider the following code
fragment:
try
{
if (n>10) throw(n);
}
catch(int a) //argument name is specified
{
cout<<“Exception-Number “<<a<<“ is greater than 10”;
//a is used inside the catch block
}
In this code segment, an argument a of type int is passed to the catch block and
hence, can be used inside the catch block.
Using Multiple Catch Statements
The programs discussed so far contain only one catch block. However, C++ also
allows us to provide multiple catch blocks to handle different types of exceptions.
The syntax for defining multiple catch blocks is as follows:
try //try block
{
//multiple throw expressions
}
catch(data_type1 parameter1) //catch block 1
{
//catch block
}
catch(data_type2 parameter2) //catch block 2
{
//catch block
}
...
catch(data_typen parameterN) //catch block N
{
//catch block
}
Note that there is only one try block in which multiple exceptions are thrown and
depending on the type of exception thrown, a particular catch block is executed.
Self-Instructional
Material 255
Exception Handling Whenever an exception is thrown, the catch blocks are searched in a sequential
order for an appropriate match. The first catch block whose data type matches
with the type of exception is executed, and other catch blocks are skipped. Once
the execution of the appropriate catch block gets over, the control passes to the
NOTES statement immediately following the last catch block. If an appropriate match is
not found, the program terminates abnormally.
Example 13.4: A program to demonstrate the concept of catching multiple
exceptions
#include<iostream>
#include<cmath>
using namespace std;
int main()
{
int a,b,c,d;
float root1,root2;
cout<<“Enter the coefficients of a quadratic equation:\n”;
cin>>a>>b>>c;
d=b*b-4*a*c;
try
{
if (a==0)
throw(1); //throwing int type
else if(d<0)
throw(1.0); //throwing double type
else if (d==0)
throw ‘c’; //throwing char type
else
{
root1=(-b+sqrt(d))/(2*a);
root2=(-b-sqrt(d))/(2*a);
cout<<“The roots are: “<<root1<<“ and “<<root2;
}
}
catch(int) //catch block 1
{
cout<<“Exception-division by zero”;
}
catch(double) //catch block 2
{
cout<<“Exception-square root of a negative number”;
}
Self-Instructional
256 Material
catch(char) //catch block 3 Exception Handling
{
cout<<“Exception-Roots are equal: “;
root1=(-b)/(2*a);
NOTES
cout<<root1;
}
return 0;
}
Second run
Enter the coefficients of a quadratic equation:
0 1 2
Exception-division by zero
Third run
Enter the coefficients of a quadratic equation:
2 4 2
Exception-Roots are equal: -1
Fourth run
Enter the coefficients of a quadratic equation:
4 5 1
The roots are: -0.25 and –1
In this example, multiple exceptions are caught and handled by different catch
blocks. If the first coefficient is zero, the exception of type int is thrown and the
catch block 1 is executed. If the value of d evaluates to a negative number, the
exception of type double is thrown and the catch block 2 is executed. Finally,
if the value of d evaluates to zero, a char exception is thrown and catch block 3
is executed. If no exception occurs, the roots of the equation are calculated and
displayed.
Catching All Exceptions
Sometimes it is not possible to predict all types of exceptions that can occur
during the program execution and hence, separate catch blocks cannot be provided
to handle all the exceptions. In such cases, a single catch block to handle multiple
exceptions can be defined. This can be achieved by using the ellipsis (...) as Self-Instructional
Material 257
Exception Handling the arguments in the catch block. The syntax for defining the catch block with
ellipsis is as follows:
catch(...)
{
NOTES
//statements to handle all exceptions
}
Example 13.5: A program to demonstrate the concept of catching all exceptions
#include<iostream>
using namespace std;
void exception_handler(int x)
{
try
{
if(x<0)throw -1;
if(x>=0 && x<=31) throw ‘c’;
if(x>255) throw 255.1;
else
cout<<“Equivalent character is: “<<char(x);
}
catch(...)
{
cout<<“Exception-either non-printable character “;
cout<<“or wrong ASCII code”;
}
}
int main()
{
int ch;
cout<<“Enter an ASCII code: “;
cin>>ch;
exception_handler(ch);
return 0;
}
The output of the program is
First run
Enter an ASCII code: 333
Exception-either non-printable character or wrong ASCII
code
Second run
Enter an ASCII code: 67
Self-Instructional Equivalent character is: C
258 Material
In this example, a single catch block having ellipsis as argument is defined for Exception Handling
catching all types of exceptions. If the user enters an ASCII code between 32 and
255, its equivalent character is displayed. Otherwise, an exception is thrown and
an appropriate message is displayed.
NOTES
As stated earlier, if an appropriate match of exception handler is not found,
the program terminates abnormally. To prevent this, catch(...) can be used
as a default exception handler along with other catch blocks to handle all those
exceptions that are not handled by any other catch block. However, it should
always be placed after all the other catch blocks; otherwise, it would prevent
other catch blocks from handling exceptions.
Catching Class Types
As stated earlier, in addition to built-in data types, exceptions of user-defined data
types such as classes can also be caught and handled. In this case, the throw
expression throws an object of the class as exception and the catch block accepts
an object of the class as argument.
Example 13.6: A program to demonstrate the concept of catching exceptions of
class type
#include<iostream>
using namespace std;
class positive
{
int n;
public:
positive(){n=0;} //default constructor
void getdata(int a)
{
if (a<0)
throw positive(); //throws a class type exception
else
n=a;
}
void display()
{ cout<<“The value is “<<n; }
};
int main()
{
int num;
positive p;
cout<<“Enter any number: “;
cin>>num;
Self-Instructional
Material 259
Exception Handling try
{
[Link](num);
[Link]();
NOTES
}
catch(positive)
{
cout<<“Exception caught-a negative value”;
}
return 0;
}
Second run
Enter any number: 23
The value is 23
In this example, a class positive is defined with a private data member n. If
a user enters a negative value for n, an exception is thrown in the
getdata()member function, which is caught by the catch block accepting a
parameter of type positive.
Sometimes a situation may arise that the exceptions, which occur while
creating the objects of a class, need to be handled. In such situation, an exception
must be thrown inside the constructor of the class. However, the throw statement
inside the constructor of the class cannot throw the object of the same class. In
this case, a new entity called exception class needs to be created. Now the
throw statement throws an object of the exception class, which is handled by the
catch block accepting a parameter of type exception class.
An exception class can be defined either globally or in the public section of
another class. Moreover, the body of the exception class can be either empty or
can contain data members and member functions. This section discusses an
exception class with an empty body.
Example 13.7: A program to demonstrate the concept of defining an exception
class inside another class
#include<iostream>
using namespace std;
class positive
{
Self-Instructional
260 Material
int n; Exception Handling
public:
class check_number { }; //exception class with empty body
positive(int a) //parameterised constructor
NOTES
{
if (a<0)
throw check_number(); //throwing an exception
//of type check_number
else
n=a;
}
void display()
{ cout<<“The value is “<<n; }
};
int main()
{
int num;
cout<<“Enter any number: “;
cin>>num;
try
{
positive p(num); //creating an object of class
[Link]();
}
catch(positive::check_number)
{
cout<<“Exception caught-a negative value”;
}
return 0;
}
The output of the program is
First run
Enter any number: -4
Exception caught-a negative value
Second run
Enter any number: 6
The value is 6
Self-Instructional
Material 261
Exception Handling Exception Handling in Base and Derived Classes
While handling exceptions that involve base as well as derived classes, proper
ordering of catch blocks is necessary. A catch block handling the exception of
NOTES derived class should be placed before the base class exception handler. If the
base class exception handler is placed before the derived class exception handler,
the base class handler catches all the derived classes’ exceptions and the derived
class handler will not be executed.
Example 13.8: A program to demonstrate the concept of exception handling in
base and derived classes
#include<iostream>
using namespace std;
class number //base class
{ };
class positive: public number //derived class
{
int p;
public:
positive(int a){p=a;}
};
int main()
{
int num=-5;
try
{
if (num<0)
throw positive(num);//exception of derived class
}
catch(number n) //catch block for base class
{
cout<<“Base class exception caught”;
}
catch(positive p) //catch block for derived class
{
cout<<“Derived class exception caught”;
}
return 0;
}
The output of the program is
Base class exception caught
Self-Instructional
262 Material
In this example, the exception of derived class positive is caught and handled Exception Handling
by the catch block of base class number as it is placed before the catch block
of derived class. However, if the order of catch blocks is changed, the output of
the program is as follows:
Derived class exception caught
NOTES
Note: If the exception of the base class is thrown, it is handled by the catch
block of base class only irrespective of the order of the catch blocks.
1. The catch block must always immediately follow the try block.
2. Proper ordering of catch blocks is necessary to handle exceptions that
involve base as well as derived classes.
13.6 SUMMARY
The C++ exception handling mechanism mainly uses three keywords, try,
throw and catch. A set of statements that needs to be monitored for the
exceptions is contained in the try block. The try block is surrounded by
curly braces and prefixed by the keyword try.
The catch block must always immediately follow the try block irrespective
of the location of the throw point.
Once an exception is thrown, the control is automatically transferred to the
catch block and the try block is terminated.
If an appropriate match is not found, the standard library function terminate()
is invoked, which by default calls the abort() function to terminate the
program abnormally.
The argument exception used with the throw statement can be either of
built- in data type such as int, float, etc. or a user-defined data type such as
class, struct, etc.
Note that it is not necessary that the exception should always be thrown
from the try block.
Self-Instructional
Material 263
Exception Handling Note that if the function containing the throw statement is called more than
once in the try block, the function call is executed as long as no exception
occurs.
When an exception is thrown, it needs to be handled appropriately.
NOTES
The programs discussed so far contain only one catch block.
Note that there is only one try block in which multiple exceptions are thrown
and depending on the type of exception thrown, a particular catch block is
executed. Whenever an exception is thrown, the catch blocks are searched
in a sequential order for an appropriate match.
Sometimes it is not possible to predict all types of exceptions that can occur
during the program execution and hence, separate catch blocks cannot be
provided to handle all the exceptions.
As stated earlier, in addition to built-in data types, exceptions of user-defined
data types such as classes can also be caught and handled.
Sometimes a situation may arise that the exceptions, which occur while
creating the objects of a class, need to be handled.
An exception class can be defined either globally or in the public section of
another class.
While handling exceptions that involve base as well as derived classes, proper
ordering of catch blocks is necessary.
Short-Answer Questions
1. Write a program to demonstrate the concept of defining an exception class
inside another class
2. Write a program to demonstrate the concept of exception handling in base
and derived classes
Self-Instructional
264 Material
Long-Answer Questions Exception Handling
1. “The C++ exception handling mechanism mainly uses three keywords, try,
throw and catch.” Discuss these in detail.
2. “The catch block is also called the exception handler and it must immediately NOTES
follow the try block that throws an exception.” Give reasons for the statement.
3. What is a throw statement? Discuss the general use of throw statements.
4. “The code that handles the exception is written in the catch block.” Explain
with example.
Self-Instructional
Material 265