Unit - 8
Exception Handling
Q1) What is Exception Handling?
A1)
- Exception is a run time error.
- Exception occurs when unusual condition or anomalies occur at run time due to logical errors.
- These unusual conditions may be division by zero, accessing element that does not exists, invalid inputs or running out of memory or disk space.
Types of Exceptions
- C++ provides standard exceptions defined in <exception>.
- These are as follows
1.std:: exception
It is parent class of all exceptions.
2.std::range_error
It occurs when we try to store a value out of range.
3.std::underflow_error
It occurs when arithmetic underflow occurs.
4.std::overflow_error
It occurs when arithmetic overflow occurs.
5.std::invalid_argument
It occurs due to invalid arguments.
Q2) What is throwing and catching exceptions?
A2)
Throwing Exceptions
Exceptions can be thrown anywhere within a code block using throw statement. The operand of the throw statement 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 an 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. You 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 ExceptionName exception
}
Above code will catch an exception of ExceptionName type. If you want to specify that a catch block should handle any type of exception that is thrown in a try block, you must put an ellipsis, ..., between the parentheses enclosing the exception declaration as follows −
Try {
// protected code
} catch(...) {
// code to handle any exception
}
The following is an example, which throws a division by zero 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 −
Division by zero condition!
Q3) What are some of the standard exceptions?
A3)
Standard Exceptions
C++ provides a list of standard exceptions defined in <exception> which we can use in our programs. These are arranged in a parent-child class hierarchy shown below −
Here is the small description of each exception mentioned in the above hierarchy −
Sr.No | Exception & Description |
1 | Std::exception An exception and parent class of all the standard C++ exceptions. |
2 | Std::bad_alloc This can be thrown by new. |
3 | Std::bad_cast This can be thrown by dynamic_cast. |
4 | Std::bad_exception This is useful device to handle unexpected exceptions in a C++ program. |
5 | Std::bad_typeid This can be thrown by typeid. |
6 | Std::logic_error An exception that theoretically can be detected by reading the code. |
7 | Std::domain_error This is an exception thrown when a mathematically invalid domain is used. |
8 | Std::invalid_argument This is thrown due to invalid arguments. |
9 | Std::length_error This is thrown when a too big std::string is created. |
10 | Std::out_of_range This can be thrown by the 'at' method, for example a std::vector and std::bitset<>::operator[](). |
11 | Std::runtime_error An exception that theoretically cannot be detected by reading the code. |
12 | Std::overflow_error This is thrown if a mathematical overflow occurs. |
13 | Std::range_error This is occurred when you try to store a value which is out of range. |
14 | Std::underflow_error This is thrown if a mathematical underflow occurs. |
Q4) Define New Exceptions
A4)
You can define your own exceptions by inheriting and overriding exception class functionality. Following is the example, which shows how you can use std::exception class to implement your own exception in standard way −
#include <iostream>
#include <exception>
Using namespace std;
Struct MyException : public exception {
const char * what () const throw () {
return "C++ Exception";
}
};
Int main() {
try {
throw MyException();
} catch(MyException& e) {
std::cout << "MyException caught" << std::endl;
std::cout << e.what() << std::endl;
} catch(std::exception& e) {
//Other errors
}
}
This would produce the following result −
MyException caught
C++ Exception
Here, what() is a public method provided by exception class and it has been overridden by all the child exception classes. This returns the cause of an exception.
Q5) Give an example Using the runtime error class
A5)
Example
#include <iostream>
#include <stdexcept>
Using namespace std;
//handling divide by zero
Float Division(float num, float den){
If (den == 0) {
Throw runtime_error("Math error: Attempted to divide by Zero\n");
}
Return (num / den);
}
Int main(){
Float numerator, denominator, result;
Numerator = 12.5;
Denominator = 0;
Try {
Result = Division(numerator, denominator);
Cout << "The quotient is " << result << endl;
}
Catch (runtime_error& e) {
Cout << "Exception occurred" << endl << e.what();
}
}
Output
Exception occurred
Math error: Attempted to divide by Zero
Q6) Give an example Using user defined exception handling
A6)
Example
#include <iostream>
#include <stdexcept>
Using namespace std;
//user defined class for handling exception
Class Exception : public runtime_error {
Public:
Exception()
: runtime_error("Math error: Attempted to divide by Zero\n") {
}
};
Float Division(float num, float den){
If (den == 0)
Throw Exception();
Return (num / den);
}
Int main(){
Float numerator, denominator, result;
Numerator = 12.5;
Denominator = 0;
//trying block calls the Division function
Try {
Result = Division(numerator, denominator);
Cout << "The quotient is " << result << endl;
}
Catch (Exception& e) {
Cout << "Exception occurred" << endl << e.what();
}
}
Output
Exception occurred
Math error: Attempted to divide by Zero
Q7) Give an example Using stack unwinding
A7)
Example
#include <iostream>
#include <stdexcept>
Using namespace std;
//defining function to handle exception
Float CheckDenominator(float den){
If (den == 0) {
Throw runtime_error("Math error: Attempted to divide by zero\n");
}
Else
Return den;
}
Float Division(float num, float den){
Return (num / CheckDenominator(den));
}
Int main(){
Float numerator, denominator, result;
Numerator = 12.5;
Denominator = 0;
Try {
Result = Division(numerator, denominator);
Cout << "The quotient is " << result << endl;
}
Catch (runtime_error& e) {
Cout << "Exception occurred" << endl << e.what();
}
}
Output
Exception occurred
Math error: Attempted to divide by zero
Q8) Give an Example of simple try-throw-catch
A8)
#include<iostream.h>
#include<conio.h>
void main()
{
int n1,n2,result;
cout<<"\nEnter 1st number : ";
cin>>n1;
cout<<"\nEnter 2nd number : ";
cin>>n2;
try
{
if(n2==0)
throw n2; //Statement 1
else
{
result = n1 / n2;
cout<<"\nThe result is : "<<result;
}
}
catch(int x)
{
cout<<"\nCan't divide by : "<<x;
}
cout<<"\nEnd of program.";
}
Output :
Enter 1st number : 45
Enter 2nd number : 0
Can't divide by : 0
End of program
The catch block contain the code to handle exception. The catch block is similar to function definition.
catch(data-type arg)
{
- - - - - - - - - -
- - - - - - - - - -
- - - - - - - - - -
};
Data-type specifies the type of exception that catch block will handle, Catch block will recieve value, send by throw keyword in try block.
Q9) Explain Multiple Catch Statements with examples
A9)
A single try statement can have multiple catch statements. Execution of particular catch block depends on the type of exception thrown by the throw keyword. If throw keyword send exception of integer type, catch block with integer parameter will get execute.
Example of multiple catch blocks
#include<iostream.h>
#include<conio.h>
void main()
{
int a=2;
try
{
if(a==1)
throw a; //throwing integer exception
else if(a==2)
throw 'A'; //throwing character exception
else if(a==3)
throw 4.5; //throwing float exception
}
catch(int a)
{
cout<<"\nInteger exception caught.";
}
catch(char ch)
{
cout<<"\nCharacter exception caught.";
}
catch(double d)
{
cout<<"\nDouble exception caught.";
}
cout<<"\nEnd of program.";
}
Output :
Character exception caught.
End of program.
Q10) Explain Rethrowing Exceptions with examples
A10)
Rethrowing exception is possible, where we have an inner and outer try-catch statements (Nested try-catch). An exception to be thrown from inner catch block to outer catch block is called rethrowing exception.
Syntax of rethrowing exceptions
Example of rethrowing exceptions
#include<iostream.h>
#include<conio.h>
void main()
{
int a=1;
try
{
try
{
throw a;
}
catch(int x)
{
cout<<"\nException in inner try-catch block.";
throw x;
}
}
catch(int n)
{
cout<<"\nException in outer try-catch block.";
}
cout<<"\nEnd of program.";
}
Output :
Exception in inner try-catch block.
Exception in outer try-catch block.
End of program.