EXCEPTION HANDLING
What is an Exception?
An exception
is a situation in which a program has an unexpected circumstance that the
section of code containing the problem is not explicitly designed to handle.
Sometimes,
exceptions can be considered as errors that occur at runtime.
Examples of commonly encountered
exceptions:
1. Falling
short of memory
2. Inability
to open a file
3. Exceeding
the bounds of an array
4. Attempting
to initialize an object to an impossible value.
C++ provides
a systematic, object oriented approach to handle exceptions.
Important Keywords of Exception Handling:
The
Exception handling of C++, uses three keywords:
1. Try:
We use a try block to surround parts of code that can generate exceptions. This
section of code is specially examined during execution to watch for any
exceptions.
2. Throw:
This keyword serves two purposes. When used within the body of a function, it
is used to throw an exception. When used in the header of a function, it is
used to specify what types of exceptions the function may throw.
3. Catch:
Every try block will usually have one or more catch blocks following it. A
catch block contains code that should be executed whenever an exception of a
specific type is caught. This allows us to customize the behavior of our
program based on what kinds of things could go wrong. It is important to notice
that catch block should come immediately after the try block.
Syntax:
try
// Try block
{
//statement 1
//statement 2
//some
erroneous statement
throw
some_object; // Throw statement
}
catch
(some_object) // Catch block
{
//Some
statements to handle the exception
}
Catching an Exception
Example 1:
#include <iostream.h>
using namespace std;
int main()
{
int
StudentAge;
cout
<< "Student Age: ";
cin
>> StudentAge;
try {
if(StudentAge
< 0)
throw
StudentAge;
cout <<
"\nStudent Age: " << StudentAge << "\n\n";
}
catch(int X)
{
cout<<”Student Age can not be
less than 0”;
}
cout
<< "\n";
return
0;
}
Single Try block and Multiple Catch
Blocks:
A single try
block can have multiple catch blocks.
Syntax:
try
{
Code to Try
}
catch(Arg1)
{
One Exception
}
catch(Arg2)
{
Another Exception
}
The compiler would
proceed in a top-down as follows:
- Following the normal flow control of
the program, the compiler enters the try block.
- If no exception occurs in the try
block, the rest of the try block is executed.
If an exception occurs in the try block, the try displays a throw
that specifies the type of error that happened.
- The compiler gets out of the try
block and examines the first catch
- If the first catch doesn’t match the thrown
error, the compiler proceeds with the next catch. This continues
until the compiler finds a catch that matches the thrown
error.
- If one of the catches matches the
thrown error, its body executes. If no catch matches the thrown
error, you have (or the compiler has) two alternatives. If there is no
catch that matches the error (which means that you didn’t provide a
matching catch), the compiler hands the program flow to the operating
system (which calls the terminate() function). Another alternative
is to include a catch whose argument is three periods: catch(…).
The catch(…) is used if no other catch, provided there was
another, matches the thrown error. The catch(…), if included as
part of a catch clause, must always be the last catch,
unless it is the only catch of the clause.
Multiple catches
are written if or when a try block is expected to throw different types of
errors. Imagine a program that requests some numbers from the user and performs
some operation on the numbers. Such a program can be written as follows:
Single Catch Block and Multiple Try
blocks
It is
possible to have a single catch block to catch exceptions thrown by multiple
throw statements.
Syntax:
try
{
//some code
throw
some_object1;
try
{
Throw some_object2;
}
}
catch(…) // this catch block catches exception of any
type
{
//statements to
handle exceptions
}
EXAMPLE:
#include <iostream>
using namespace std;
int main()
{
int
StudentAge;
cout
<< "Student Age: ";
cin
>> StudentAge;
try {
if(StudentAge
< 0)
throw;
cout <<
"\nStudent Age: " << StudentAge << "\n\n";
}
catch(...)
{
}
cout
<< "\n";
return
0;
}
Re-Throwing Exceptions
It is
possible to re-throw exception objects which were caught once in a catch block.
Re-throwing exceptions can be done any number of times. But while re-throwing
exception objects, the throw statement will not take any arguments.
EXAMPLE:
#include <iostream.h>
#include<conio.h>
void sum(int i, int j)
{
cout<<”in
function sum()”;
try
{
if(i==0)
throw i;
else
cout<<”subtraction
of i&j”<<i-j;
}
catch(int)
{
cout<<”caught
null values”;
throw; //rethrowing
}
cout<<”end
of Sum()”;
}
void main()
{
cout<<”in
main() function”;
try
{
sum(10,6);
sum(0,5);
}
catch(int)
{
cout<<”caught
null value inside main()”;
}
cout<<”End
of Main()”;
}
Nesting of try, catch blocks:
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
|
try {
try {
// code here
}
catch (int n) {
throw;
}
}
catch (...) {
cout << "Exception occurred";
}
|
Why Exception Handling is necessary?
In C++,
exception handling is useful because it makes it easy to separate the error
handling code from the code written to handle the chores of the program. Doing
so makes reading and writing the code easier.