Basics of Exceptions in C++
Exception Handling in C++ - Part 1
Forward: In this part of the series we look at the basics of exception in C++.
By: Chrysanthus Date Published: 24 Aug 2012
Basics of Exceptions in C++
Note: If you cannot see the code or if you think anything is missing (broken link, image absent), just contact me at forchatrans@yahoo.com. That is, contact me for the slightest problem you have about what you are reading.
Runtime Error Example
Consider the following code:
#include <iostream>
using namespace std;
int main()
{
int numerator = 8;
int denominator = 2;
if (denominator != 0 )
{
int answer = numerator/denominator;
cout << answer;
}
else
{
cout << "Division by zero is not allowed!";
}
return 0;
}
This code basically divides two numbers. In life you cannot divide a number by zero. Assuming that the denominator is input by the user, he may input zero. The division (process) by zero should not be allowed.
Let us look at what is in the code: the first two statements in the main function block are initialization of integers. The division should take place in the if-block. The if-condition checks whether the denominator is zero. If it is not, the division takes place in the if-block. If it is, the else part of the if-construct displays an error message to the user. This code segment is OK, because if the denominator is zero, the if-block will not be executed and no division will take place. With the above code, the execution of the program continues after the if/else construct.
This if/else construct does the division and prevents runtime error from taking place. The if-block does the division; the if-condition checks if error would occur; if error would occur, the else block display an alert message and the if-block and division are not executed.
With exception handling, you have what is called the try/catch construct. The try block has an important expression, which is, throw. throw takes an argument (operand).
In the above if/else construct, the code segment of interest, which is the segment required, is the if-block. This if-block is what does the division. With Exception handling that code segment of interest goes into the try-block; the error message code segment or error handler code segment goes into the catch-block. The throw expression in the try-block calls the catch-block passing its argument to it. The catch construct is like a function. This is the basic syntax for exception handling,
try
{
//statements of interest
throw identT;
}
catch (int identC)
{
//handle the error
}
The argument for the throw expression does not go into parentheses. The catch-construct has a parameter. The argument for the throw expression must be of the same type as the parameter of the catch construct. You are the one who decides on the object type of the parameter, which is the same as the object type of the argument. The argument of the throw expression can be a literal or an identifier. You are the one who decides on that. You take these decisions depending on the nature of the error and how you want to handle the error.
The catch-block should immediately follow the try-block in your typing, as in the above syntax.
The previous code is re-written using the try/catch construct as follows:
#include <iostream>
using namespace std;
int main()
{
int numerator = 8;
int denominator = 2;
try
{
if (denominator != 0 )
{
int answer = numerator/denominator;
cout << answer;
}
else
{
throw 0;
}
}
catch (int e)
{
if (e == 0)
cout << "Division by zero is not allowed!";
}
return 0;
}
In the initialization of the denominator, above, replace the right operand with 0 and test the code again.
Now the try-block may actually have an if/else construct with many throws. The catch block may correspondingly have if/else constructs. You are the one who decides on which argument to give for a throw expression. In the catch block, the value of a particular argument can determine what you code as error message. Referring to the above code, one argument may be 0, another may be 5, another may be 10, and so on; you are the one to choose the values. Each throw normally takes one argument. If the arguments are of different object types, then you need one catch block for each type (see later).
You can put what you need for the try block in a function as illustrated below:
#include <iostream>
using namespace std;
int numerator = 8;
int denominator = 0;
void errFn()
{
if (denominator != 0 )
{
int answer = numerator/denominator;
cout << answer;
}
else
{
throw 0;
}
}
int main()
{
try
{
errFn();
}
catch (int e)
{
cout << "Division by zero is not allowed!";
}
return 0;
}
Note that in the catch block, this time, I have not used an if-statement. This is because, if the parameter of the catch construct is of the same type as the argument of the throw expression, then the catch-construct will catch the exception (will catch what has been thrown). Under this condition, it is not obligatory to use the identifier of the catch parameter in the catch-block.
Well, also note that the initialization of the numerator and denominator are now outside the main block (and the function block) and up in the code, so that they can be seen by any block in the code.
We have learned that the throw expression can be in the try block directly or in a function called by the try block. However, the catch block remains attached to the try block, whether or not the throw expression is in the try block directly or in function called by the try block.
Note: In practical programming, most catch blocks just send an error message to the user of the program; they do not really correct the error.
Let us take a break here and continue in the next part of the series.
Chrys
Related Courses
C++ CourseRelational Database and Sybase
Windows User Interface
Computer Programmer – A Jack of all Trade – Poem
NEXT