Deitel & Associates, Inc. Logo

Back to
digg.png delicious.png blinkit.png furl.png
C++ How to Program, 5/e

© 2005
pages: 1500
Buy the Book!
Amazon logo
InformIT logo

This tutorial introduces C++ exception handling. 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. The techniques presented in this tutorial enable programmers to write robust, fault-tolerant programs that are able to deal with problems that may arise, and continue executing or terminate gracefully. We demonstrate exception-handling techniques with an example in which a function generates an exception when an attempt is made to divide by zero. The program catches this exception, issues an error message, then continues normal execution. This tutorial is intended for students and professionals who are already familiar with building C++ classes.

Download the code examples for this tutorial.

[Note: This tutorial is an excerpt (Section 16.3) of Chapter 16, Exception Handling, from our textbook C++ How to Program, 5/e. These tutorials may refer to other chapters or sections of the book that are not included here. Permission Information: Deitel, Harvey M. and Paul J., C++ HOW TO PROGRAM, ©2005, pp.812-818. Electronically reproduced by permission of Pearson Education, Inc., Upper Saddle River, New Jersey.]

16.3 Example: Handling an Attempt to Divide by Zero (Continued)

Termination Model of Exception Handling

If an exception occurs as the result of a statement in a try block, the try block expires (i.e., terminates immediately). Next, the program searches for the first catch handler that can process the type of exception that occurred. The program locates the matching catch by comparing the thrown exception’s type to each catch’s exception-parameter type until the program finds a match. A match occurs if the types are identical or if the thrown exception’s type is a derived class of the exception-parameter type. When a match occurs, the code contained within the matching catch handler executes. When a catch handler finishes processing by reaching its closing right brace (}), the exception is considered handled and the local variables defined within the catch handler (including the catch parameter) go out of scope. Program control does not return to the point at which the exception occurred (known as the throw point), because the try block has expired. Rather, control resumes with the first statement (line 49) after the last catch handler following the try block. This is known as the termination model of exception handling. [Note: Some languages use the resumption model of exception handling, in which, after an exception is handled, control resumes just after the throw point.] As with any other block of code, when a try block terminates, local variables defined in the block go out of scope.

Common Programming Error
Common Programming Error 16.4
Logic errors can occur if you assume that after an exception is handled, control will return to the first statement after the throw point.
Error-Prevention Tip
Error-Prevention Tip 16.2
With exception handling, a program can continue executing (rather than terminating) after dealing with a problem. This helps ensure the kind of robust applications that contribute to what is called mission-critical computing or business-critical computing.

If the try block completes its execution successfully (i.e., no exceptions occur in the try block), then the program ignores the catch handlers and program control continues with the first statement after the last catch following that try block. If no exceptions occur in a try block, the program ignores the catch handler(s) for that block.

If an exception that occurs in a try block has no matching catch handler, or if an exception occurs in a statement that is not in a try block, the function that contains the statement terminates immediately, and the program attempts to locate an enclosing try block in the calling function. This process is called stack unwinding and is discussed in Section 16.8.

Flow of Program Control When the User Enters a Nonzero Denominator

Consider the flow of control when the user inputs the numerator 100 and the denominator 7 (i.e., the first two lines of output in Fig. 16.2). In line 16, function quotient determines that the denominator does not equal zero, so line 20 performs the division and returns the result (14.2857) to line 38 as a double (the static_cast< double > in line 20 ensures the proper return value type). Program control then continues sequentially from line 38, so line 39 displays the division result and line 40 is the end of the try block. Because the try block completed successfully and did not throw an exception, the program does not execute the statements contained in the catch handler (lines 43–47), and control continues to line 49 (the first line of code after the catch handler), which prompts the user to enter two more integers.

Flow of Program Control When the User Enters a Denominator of Zero

Now let us consider a more interesting case in which the user inputs the numerator 100 and the denominator 0 (i.e., the third and fourth lines of output in Fig. 16.2). In line 16, quotient determines that the denominator equals zero, which indicates an attempt to divide by zero. Line 17 throws an exception, which we represent as an object of class DivideByZeroException (Fig. 16.1).

Note that, to throw an exception, line 17 uses keyword throw followed by an operand that represents the type of exception to throw. Normally, a throw statement specifies one operand. (In Section 16.5, we discuss how to use a throw statement that specifies no operands.) The operand of a throw can be of any type. If the operand is an object, we call it an exception object—in this example, the exception object is an object of type DivideByZeroException. However, a throw operand also can assume other values, such as the value of an expression (e.g., throw x > 5) or the value of an int (e.g., throw 5). The examples in this chapter focus exclusively on throwing exception objects.

Common Programming Error
Common Programming Error 16.5
Use caution when throwing the result of a conditional expression (?:), because promotion rules could cause the value to be of a type different from the one expected. For example, when throwing an int or a double from the same conditional expression, the conditional expression converts the int to a double. However, the catch handler always catches the result as a double, rather than catching the result as a double when a double is thrown, and catching the result as an int when an int is thrown.

As part of throwing an exception, the throw operand is created and used to initialize the parameter in the catch handler, which we discuss momentarily. In this example, the throw statement in line 17 creates an object of class DivideByZeroException. When line 17 throws the exception, function quotient exits immediately. Therefore, line 17 throws the exception before function quotient can perform the division in line 20. This is a central characteristic of exception handling: A function should throw an exception before the error has an opportunity to occur.

Because we decided to enclose the invocation of function quotient (line 38) in a try block, program control enters the catch handler (lines 43–47) that immediately follows the try block. This catch handler serves as the exception handler for the divide-by-zero exception. In general, when an exception is thrown within a try block, the exception is caught by a catch handler that specifies the type matching the thrown exception. In this program, the catch handler specifies that it catches DivideByZeroException objects—this type matches the object type thrown in function quotient. Actually, the catch handler catches a reference to the DivideByZeroException object created by function quotient’s throw statement (line 17).

Performance Tip
Performance Tip 16.2
Catching an exception object by reference eliminates the overhead of copying the object that represents the thrown exception.
Good Programming Practice
Good Programming Practice 16.1
Associating each type of runtime error with an appropriately named exception object improves program clarity.

The catch handler’s body (lines 45–46) prints the associated error message returned by calling function what of base-class runtime_error. This function returns the string that the DivideByZeroException constructor (lines 12–13 in Fig. 16.1) passed to the runtime_error base-class constructor.

Additional Pages in this Tutorial: Page 1 | 2 | 3 | 4
Tutorial Index