EXCEPTION HANDLING
Introduction
An exception is an indication of a problem that occurs during a program's execution. The name "exception" implies that the problem occurs infrequently if the "rule" is that a statement normally executes correctly, then the "exception to the rule" is that a problem occurs. Exception handling enables programmers to create applications that can resolve (or handle) exceptions. In many cases, handling an exception allows a program to continue executing as if no problem had been encountered. A more severe problem could prevent a program from continuing normal execution, instead requiring the program to notify the user of the problem before terminating in a controlled manner. The features presented in this chapter enable programmers to write robust and fault-tolerant programs that are able to deal with problems that may arise and continue executing or terminate gracefully.
- Exception handling helps improve a program's fault tolerance.
- Exception handling provides a standard mechanism for processing errors. This is especially important when working on a project with a large team of programmers.
Exception-Handling Overview
Program logic frequently tests conditions that determine how program execution proceeds. Consider the following pseudocode:
Perform a task
If the preceding task did not execute correctly
Perform error processing
Perform next task
If the preceding task did not execute correctly
Perform error processing
...
In this pseudocode, we begin by performing a task. We then test whether that task executed correctly. If not, we perform error processing. Otherwise, we continue with the next task. Although this form of error handling works, intermixing program logic with error-handling logic can make the program difficult to read, modify, maintain and debug specially in large applications.
- If the potential problems occur infrequently, intermixing program logic and error-handling logic can degrade a program's performance, because the program must (potentially frequently) perform tests to determine whether the task executed correctly and the next task can be performed.
Exception handling enables the programmer to remove error-handling code from the "main line" of the program's execution, which improves program clarity and enhances modifiability. Programmers can decide to handle any exceptions they choose all exceptions, all exceptions of a certain type or all exceptions of a group of related types (e.g., exception types that belong to an inheritance hierarchy). Such flexibility reduces the likelihood that errors will be overlooked and thereby makes a program more robust.
With programming languages that do not support exception handling, programmers often delay writing error-processing code or sometimes forget to include it. This results in less robust software products. C++ enables the programmer to deal with exception handling easily from the inception of a project.
Example 1: Divide by Zero
Let us consider a simple example of exception handling . The purpose of this example is to prevent a common arithmetic problemdivision by zero. In C++, division by zero using integer arithmetic typically causes a program to terminate prematurely. In floating-point arithmetic, division by zero is allowedit results in positive or negative infinity, which is displayed as INF or -INF.
// Class DivideByZeroException definition.
#include // stdexcept header file contains runtime_error
using std::runtime_error; // standard C++ library class runtime_error
// DivideByZeroException objects should be thrown by functions
// upon detecting division-by-zero exceptions
class DivideByZeroException : public runtime_error
{
public:
// constructor specifies default error message
DivideByZeroException::DivideByZeroException()
: runtime_error( "attempted to divide by zero" ) {}
}; // end class DivideByZeroException
Exception-handling example :2 that throws exceptions
// A simple exception-handling example that checks for
// divide-by-zero exceptions.
#include
using std::cin;
using std::cout;
using std::endl;
#include "DivideByZeroException.h" // DivideByZeroException class
// perform division and throw DivideByZeroException object if
// divide-by-zero exception occurs
double quotient( int numerator, int denominator )
{
// throw DivideByZeroException if trying to divide by zero
if ( denominator == 0 )
throw DivideByZeroException(); // terminate function
// return division result
return static_cast( numerator ) / denominator;
} // end function quotient
int main()
{
int number1; // user-specified numerator
int number2; // user-specified denominator
double result; // result of division
cout << "Enter two integers (end-of-file to end): ";
// enable user to enter two integers to divide
while ( cin >> number1 >> number2 )
{
// try block contains code that might throw exception // and code that should not execute if an exception occurs
try
{
result = quotient( number1, number2 );
cout << "The quotient is: " << result << endl;
} // end try
// exception handler handles a divide-by-zero exception
catch ( DivideByZeroException ÷ByZeroException )
{
cout << "Exception occurred: "
<< divideByZeroException.what() << endl;
} // end catch
cout << "\nEnter two integers (end-of-file to end): ";
} // end while
cout << endl;
return 0; // terminate normally
} // end main
OUTPUT :
Enter two integers (end-of-file to end): 100 7
The quotient is: 14.2857
Enter two integers (end-of-file to end): 100 0
Exception occurred: attempted to divide by zero
Enter two integers (end-of-file to end): ^Z
In this example, we define a function named quotient that receives two integers input by the user and divides its first int parameter by its second int parameter. Before performing the division, the function casts the first int parameter's value to type double. Then, the second int parameter's value is promoted to type double for the calculation. So function quotient actually performs the division using two double values and returns a double result.
Although division by zero is allowed in floating-point arithmetic, for the purpose of this example, we treat any attempt to divide by zero as an error. Thus, function quotient tests its second parameter to ensure that it is not zero before allowing the division to proceed. If the second parameter is zero, the function uses an exception to indicate to the caller that a problem occurred. The caller (main in this example) can then process this exception and allow the user to type two new values before calling function quotient again. In this way, the program can continue to execute even after an improper value is entered, thus making the program more robust.
The example consists of two filesDivideByZeroException.h (EXAMPLE 1) defines an exception class that represents the type of the problem that might occur in the example, and (EXAMPLE 2) defines the quotient function and the main function that calls it. Function main contains the code that demonstrates exception handling.