1 handling exceptions cosc 1567 c++ programming lecture 11

48
1 Handling Exceptions Handling Exceptions COSC 1567 COSC 1567 C++ Programming C++ Programming Lecture 11

Upload: jeanette-rosborough

Post on 15-Jan-2016

230 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: 1 Handling Exceptions COSC 1567 C++ Programming Lecture 11

11

Handling ExceptionsHandling Exceptions

COSC 1567COSC 1567

C++ ProgrammingC++ Programming

Lecture 11

Page 2: 1 Handling Exceptions COSC 1567 C++ Programming Lecture 11

22

ObjectivesObjectives• In this lecture, you will learn:

• About the limitations of traditional error-handling methods

• How to throw exceptions

• How to use try blocks

• How to catch exceptions

• How to use multiple throw statements and multiple catch blocks

• How to throw objects

• How to use the default exception handler

• How to use exception specifications

• About unwinding the stack

• How to handle memory allocation exceptions

Page 3: 1 Handling Exceptions COSC 1567 C++ Programming Lecture 11

33

Understanding the Limitations Understanding the Limitations of Traditional Error Handlingof Traditional Error Handling

• Many C++ programs contain code similar to the code in Figure 12-1

• The program uses the exit() function, which forces the program to end

• When you use the exit() function, the program ends abruptly• If the program is a spreadsheet or a game, the user might

become annoyed that the program has prematurely stopped working

Page 4: 1 Handling Exceptions COSC 1567 C++ Programming Lecture 11

44

Understanding the Limitations Understanding the Limitations of Traditional Error Handlingof Traditional Error Handling

•A slightly better alternative to exit() involves using the atexit() function•The atexit() function requires a function name as its argument; this function is then registered with atexit(), which means the named function is called automatically whenever the exit() function executes

Ex11-1.cpp

Page 5: 1 Handling Exceptions COSC 1567 C++ Programming Lecture 11

55

Understanding the Limitations Understanding the Limitations of Traditional Error Handlingof Traditional Error Handling

• A general rule of modular programming is that a function should be able to determine an error situation; but not necessarily take action on it

• The function in Figure 12-4 returns a 1 if the dataEntryRoutine() function detects an error, and a 0 if it does not

Page 6: 1 Handling Exceptions COSC 1567 C++ Programming Lecture 11

66

Understanding the Limitations Understanding the Limitations of Traditional Error Handlingof Traditional Error Handling

• The calling main() function checks the return value of the function and takes appropriate action, printing an error message or not

• However, this error-handling technique has at least two drawbacks based on the following rules:– A function can return, at most, only one value

– When a function returns a value, it must return only the type indicated as its return type

• In the example in Figure 12-4, you could work around the problem of losing one of the values by rewriting the dataEntryRoutine() function so that sometimes it returns the userEntry, and sometimes it returns the error code

Page 7: 1 Handling Exceptions COSC 1567 C++ Programming Lecture 11

77

Program that Uses Program that Uses dataEntryRoutine() with Error CodedataEntryRoutine() with Error Code

Page 8: 1 Handling Exceptions COSC 1567 C++ Programming Lecture 11

88

Understanding the Limitations Understanding the Limitations of Traditional Error Handlingof Traditional Error Handling

• As another remedy, you could write the dataEntryRoutine() function so it accepts the address of the userEntry variable from main()

• However, allowing functions to access and alter passed variable values violates the general principle of encapsulation, and increases the data coupling of the function

• Second, any error code returned by a function must be the same type as the function’s return type

Page 9: 1 Handling Exceptions COSC 1567 C++ Programming Lecture 11

99

Throwing ExceptionsThrowing Exceptions

• A function can contain code to check for errors, and send a message when it detects an error

• In object-oriented terminology, an exception is a message (an object) that is passed from the place where a problem occurs to another place that will handle the problem

• The general principle underlying good object-oriented error handling is that any called function should check for errors, but should not be required to handle an error if one is found

Page 10: 1 Handling Exceptions COSC 1567 C++ Programming Lecture 11

1010

Throwing ExceptionsThrowing Exceptions

• When an object-oriented program detects an error within a function, the function should send an error message to the calling function, or throw an exception

• A throw resembles a return statement in a function, except that the execution of the program does not continue from where the function was called

Page 11: 1 Handling Exceptions COSC 1567 C++ Programming Lecture 11

1111

Throwing ExceptionsThrowing Exceptions

• You throw an exception by using the keyword throw followed by any C++ object, including an object that is a built-in scalar type, such as an int or a double; a nonscalar type, such as a string or numeric array; or even a programmer-defined object

• A function can make more than one throw

Page 12: 1 Handling Exceptions COSC 1567 C++ Programming Lecture 11

1212

Throwing ExceptionsThrowing Exceptions

• When you use the version of the dataEntry() function shown in Figure 12-7, if the user enters a value between 0 and 12 inclusive, the actual value is returned to the calling function when the function ends

Page 13: 1 Handling Exceptions COSC 1567 C++ Programming Lecture 11

1313

Using Try BlocksUsing Try Blocks

• A try block consists of one or more statements that the program attempts to execute, but that might result in thrown exceptions

• A try block includes the following components:

– The keyword try

– An opening curly brace

– The code that is tried

– A closing curly brace

Page 14: 1 Handling Exceptions COSC 1567 C++ Programming Lecture 11

1414

A main() Function Containing A main() Function Containing a Try Blocka Try Block

Page 15: 1 Handling Exceptions COSC 1567 C++ Programming Lecture 11

1515

Using Try BlocksUsing Try Blocks

• In Figure 12-8, the call to the dataEntry() function occurs within the highlighted try block

• When dataEntry() executes, if the userEntry is valid, then no exception is thrown, and main() executes to the end, using the valid value returned by the dataEntry() function

• If the dataEntry() function is called from a try block, as in Figure 12-8, then you can deal with the error situation more elegantly and less abruptly than with an exit() call

• You handle the thrown exception by catching it

Page 16: 1 Handling Exceptions COSC 1567 C++ Programming Lecture 11

1616

Catching ExceptionsCatching Exceptions

• To handle a thrown object, you include one or more catch blocks in your program immediately following a try block

• A catch block includes the following components:– The keyword catch

– A single argument in parentheses

– An opening curly brace

– One or more statements that describe the exception action to be taken

– A closing curly brace

• Figure 12-9 shows a dataEntry() function that throws a string error message if the user enters a negative number

Page 17: 1 Handling Exceptions COSC 1567 C++ Programming Lecture 11

1717

Catching ExceptionsCatching Exceptions

Page 18: 1 Handling Exceptions COSC 1567 C++ Programming Lecture 11

1818

Catching ExceptionsCatching Exceptions

• After executing the catch

block, the main() program

continues

• The value shown is

garbage because in the

program, userValue is

assigned a valid value

only when dataEntry() is

completed

Ex11-2.cpp

Page 19: 1 Handling Exceptions COSC 1567 C++ Programming Lecture 11

1919

Catching ExceptionsCatching Exceptions

• To avoid seeing this garbage value, you could take one of several actions:

– Initialize userValue when it is declared in the main() function; its value will change only if the try block is successful

– Assign a dummy value to userValue within the catch block, as well as within the try block. If the try block is successful, then userValue holds the value entered by the user. If the try block is unsuccessful, then userValue holds the assigned dummy value

– Declare a flag variable set to 0, then set it to 1 within the catch block to indicate an exception was thrown.

Page 20: 1 Handling Exceptions COSC 1567 C++ Programming Lecture 11

2020

Catching ExceptionsCatching Exceptions

• If you want a catch block to execute, it must catch the correct type of argument thrown from a try block

• In the steps reviewed on pages 455 to 456 of the textbook, you create a passwordEntry() function that asks a user to supply a password

Page 21: 1 Handling Exceptions COSC 1567 C++ Programming Lecture 11

2121

Catching ExceptionsCatching ExceptionsEx11-3.cpp

Page 22: 1 Handling Exceptions COSC 1567 C++ Programming Lecture 11

2222

Using Multiple Throw Statements Using Multiple Throw Statements and Multiple Catch Blocksand Multiple Catch Blocks

• You can write a function to throw any number of exceptions, and you can provide multiple catch blocks to react appropriately to each type of exception that is thrown

• You can create a dataEntry() function that throws a string message when the user enters a negative number, but throws an invalid value when the user enters a number that is more than 12

• When you run the program in Figure 12-14, if no exception is thrown, the program bypasses both catch blocks and prints the valid value, as shown in Figure 12-15

Page 23: 1 Handling Exceptions COSC 1567 C++ Programming Lecture 11

2323

A dataEntry() Function that A dataEntry() Function that Throws Two Types of ExceptionsThrows Two Types of Exceptions

Page 24: 1 Handling Exceptions COSC 1567 C++ Programming Lecture 11

2424

Using Multiple Throw Statements Using Multiple Throw Statements and Multiple Catch Blocksand Multiple Catch Blocks

Ex12-4

Page 25: 1 Handling Exceptions COSC 1567 C++ Programming Lecture 11

2525

Throwing ObjectsThrowing Objects

• Just as simple variables such as doubles, integers, and strings can be thrown via exception-handling techniques, programmer-defined class objects also can be thrown

• This approach is particularly useful in two types of situations:

– If a class object contains errors, you may want to throw the entire object, rather than just one data member or a string message

– Whenever you want to throw two or more values, you can encapsulate them into a class object so that they can be thrown together

Page 26: 1 Handling Exceptions COSC 1567 C++ Programming Lecture 11

2626

Throwing Standard Class Throwing Standard Class ObjectsObjects

• Figure 12-19 shows an Employee class with two data fields, empNum and hourlyRate

• The insertion operator is overloaded in the same way you have seen it coded in many other classes, but in this Employee class, the extraction operator has been overloaded to throw an exception

• Any program that uses the Employee class can catch the thrown Employee object and handle it appropriately for the application

Page 27: 1 Handling Exceptions COSC 1567 C++ Programming Lecture 11

2727

The Employee ClassThe Employee Class

Page 28: 1 Handling Exceptions COSC 1567 C++ Programming Lecture 11

2828

Throwing Standard Class Throwing Standard Class ObjectsObjects

• A few possibilities include:– A program might assign default values to any Employee

whose data entry resulted in an exception– A program that tests the accuracy of data entry operators

might store caught exceptions just as they are entered and count them

– A program that is used when hiring Employees for a special assignment that pays more than the usual maximum might ignore the high-end salary violations

– A program might refuse to accept an Employee with an exception, and force the user to re-enter the values, as in the main() program shown in Figure 13-20

Page 29: 1 Handling Exceptions COSC 1567 C++ Programming Lecture 11

2929

A main() Program that Instantiates A main() Program that Instantiates Three Employee ObjectsThree Employee Objects

Page 30: 1 Handling Exceptions COSC 1567 C++ Programming Lecture 11

3030

Throwing Standard Class Throwing Standard Class ObjectsObjects

• The program in Figure 12-20 declares an array of three Employee objects

• When you include multiple catch blocks in a program, the first catch block that can accept a thrown object is the one that will execute

Ex11-5.cpp

Page 31: 1 Handling Exceptions COSC 1567 C++ Programming Lecture 11

3131

Throwing Exception ObjectsThrowing Exception Objects

• You can create a class that represents an exception

• Figure 12-22 shows a Customer class that is similar to many classes you already have worked with

• Each Customer holds data fields for a customer number and a balance due, and has access to overloaded extraction and insertion operators that you can use for input and output

Page 32: 1 Handling Exceptions COSC 1567 C++ Programming Lecture 11

3232

The Customer ClassThe Customer Class

Page 33: 1 Handling Exceptions COSC 1567 C++ Programming Lecture 11

3333

Throwing Exception ObjectsThrowing Exception Objects

• Figure 12-23 shows the CustomerException class• Its data members include a Customer object and a string

message, and its constructor requires values for both

Page 34: 1 Handling Exceptions COSC 1567 C++ Programming Lecture 11

3434

Throwing Exception ObjectsThrowing Exception Objects

• Figure 12-24 shows a main() program that declares an array of four Customer objects

• In this program a loop contains four calls to the overloaded operator >>() function

• Figure 12-25 shows the output of a typical execution of the program in which some of the Customers exceed the credit limit and others do not

Page 35: 1 Handling Exceptions COSC 1567 C++ Programming Lecture 11

3535

Program that Instantiates Program that Instantiates Four CustomersFour Customers

Page 36: 1 Handling Exceptions COSC 1567 C++ Programming Lecture 11

3636

Output of Typical Execution of the Output of Typical Execution of the CustomerException ProgramCustomerException Program

Ex11-6.cpp

Page 37: 1 Handling Exceptions COSC 1567 C++ Programming Lecture 11

3737

Using the Default Exception Using the Default Exception HandlerHandler

• When any object is thrown with a throw statement, then a subsequent catch block has a usable match if one of the following conditions is true:– The type of the thrown object and the type of the catch

argument are identical (for example, int and int)– The type of the thrown object and the type of the catch

argument are the same, except the catch contains the const qualifier, a reference qualifier, or both (for example, int can be caught by const int, int&, or const int&)

– The catch argument type is a parent class of the thrown argument

Page 38: 1 Handling Exceptions COSC 1567 C++ Programming Lecture 11

3838

Using the Default Exception Using the Default Exception HandlerHandler

• If you throw an argument and no catch block exists with an acceptable argument type, then the program terminates

• To avoid termination, you can code a default exception handler that catches any type of object not previously caught

• Ex11-7.cpp demonstrate that a default catch block works as expected

• You create an Order class whose data entry function accepts several values and throws a variety of exception types

Ex11-7.cpp

Page 39: 1 Handling Exceptions COSC 1567 C++ Programming Lecture 11

3939

Unwinding the StackUnwinding the Stack

• When you write a function, you can try a function call and, if the function you call throws an exception, you can catch the exception

• However, if your function that calls the exception-throwing function doesn’t catch the exception, then a function that calls your function can still catch the exception

• A simpler way to say this is that if function A calls function B, and function B calls function C, and function C throws an exception, then if B does not catch the exception, function A can

Page 40: 1 Handling Exceptions COSC 1567 C++ Programming Lecture 11

4040

Unwinding the StackUnwinding the Stack

• If no function catches the exception, then the program terminates

• This process is called unwinding the stack, because each time you call a function, the address of the place to which the program should return is stored in a memory location called the stack

• Figure 12-28 shows a KennelReservation class that holds information about boarding a Do

• Each KennelReservation includes a kennel number, a month and day for the reservation, and a Dog

Page 41: 1 Handling Exceptions COSC 1567 C++ Programming Lecture 11

4141

The Dog ClassThe Dog Class

Page 42: 1 Handling Exceptions COSC 1567 C++ Programming Lecture 11

4242

The KennelReservation ClassThe KennelReservation Class Ex11-8.cpp

Page 43: 1 Handling Exceptions COSC 1567 C++ Programming Lecture 11

4343

Unwinding the StackUnwinding the Stack

• Within the KennelReservation function in Figure

12-28, both highlighted exception specifications

could be deleted, and the class still would

function properly

• Figure 12-29 shows a main() function that

instantiates a KennelReservation object, and

Figure 12-30 shows a typical execution

Page 44: 1 Handling Exceptions COSC 1567 C++ Programming Lecture 11

4444

Unwinding the StackUnwinding the Stack

Page 45: 1 Handling Exceptions COSC 1567 C++ Programming Lecture 11

4545

SummarySummary

• A popular traditional way to handle error situations was to terminate the program

• A superior alternative to traditional error-handling techniques is called exception handling

• The general principle underlying good object-oriented error handling is that any function that is called should check for errors, but should not be required to handle an error if it finds one

• When a function might cause an exception, and therefore includes a throw statement to handle errors, the call to potentially offending functions should be placed within a try block

Page 46: 1 Handling Exceptions COSC 1567 C++ Programming Lecture 11

4646

SummarySummary

• To handle a thrown object, you include one or more catch blocks in your program immediately following a try block

• If you want a catch block to execute, it must catch the correct type of argument thrown from a try block

• You can write a function to throw any number of exceptions, and you can provide multiple catch blocks to react appropriately to each type of exception that is thrown

Page 47: 1 Handling Exceptions COSC 1567 C++ Programming Lecture 11

4747

SummarySummary

• Just as simple variables such as doubles, integers, and strings can be thrown via exception-handling techniques, so can programmer-defined class objects

• You can create a class that represents an exception

• The class is instantiated only when an exception occurs

Page 48: 1 Handling Exceptions COSC 1567 C++ Programming Lecture 11

4848

SummarySummary

• If you throw an argument and no catch block exists with an acceptable argument type, then the program terminates

• You can explicitly indicate the exception that a function can possibly throw by writing an exception specification, which is a declaration of a function’s possible throw types

• When you allocate memory, it is always possible that there is not enough memory available, so the creators of C++ have created an out of memory exception handler for you called set_new_handler()

12