Object-Oriented Programming Exception Handling 1
C++ Exception Handling Topics Exception Handling C++ Exception Handling Basics Throwing and Catching Exceptions Constructors, Destructors and Exceptions 2
An Exception is An unusual, often unpredictable event, detectable by software or hardware, that requires special processing; also, in C++, a variable or class object that represents an exceptional event. An exception handler is a section of program code that is executed when a particular exception occurs. 3
Assertions 4
Program Segment Example 5
When to use assert Catching the program logic errors. Use assertion statements to catch logic errors. You can set an assertion on a condition that must be true according to your program logic. The assertion only has an effect if a logic error occurs. Checking the results of an operation. Use assertion statements to check the result of an operation. Assertions are most valuable for testing operations which results are not so obvious from a quick visual inspection. Testing the error conditions that supposed to be handled. Use assertions to test for error conditions at a point in your code where errors supposed to be handled. 6
Exception Handling Basics Exception handling is for situations where the function that detects the error cannot deal with it Such a function will throw an exception, and hope there is an exception handler to catch it There is no guarantee that the exception will be caught If it s not caught the program terminates 7
...Exception Handling Basics Exceptions are thrown and caught using try and catch blocks try {... catch {... Code in the try block can throw an exception The catch blocks contains handlers for the various exceptions When an exception is thrown in the try block, the catch blocks are searched for an appropriate exception handler 8
Syntax The try-block: try {compound-statement handler-list handler-list here The throw-expression: throw expression { The handler: catch (exception-declaration) compound-statement exception-declaration: type-specifier-list here 9
Exception-Handling Overview Throw point Location in try block where exception occurred If exception handled» Program skips remainder of try block» Resumes after catch blocks If not handled» Function terminates» Looks for enclosing catch block If no exception Program skips catch blocks 10
Execution of try-catch A statement throws an exception No statements throw an exception Control moves directly to exception handler Exception Handler Statements to deal with exception are executed Statement following entire try-catch statement 11
Simple Exception-Handling Example: Divide by Zero Keyword throw Throws an exception» Use when error occurs Can throw almost anything (exception object, integer, etc.)» throw myobject;» throw 5; Exception objects Base class exception ( <exception> ) Constructor can take a string (to describe exception) Member function what() returns that string 12
#include <iostream> using namespace std; Creating an error object to throw class DivideByZeroError { public: DivideByZeroError() : message("divide by Zero") { void printmessage() const {cout << message; private: const char* message; ; int main(){ DivideByZeroError err; err.printmessage(); return 0; Divide by Zero 13
Divide Function that throws an exception #include <iostream> using namespace std; float quotient(int numerator, int denominator) { if (denominator == 0) throw DivideByZeroError(); return (float) numerator / denominator; int main(){ int i = 10, j = 3; cout << quotient(i,j) << \n ; return 0; 3.33333 14
Execution Generating an Error (without try block) #include <iostream.h> float quotient(int numerator, int denominator) { if (denominator == 0) throw DivideByZeroError(); return (float) numerator / denominator; main(){ int i = 10, j = 0; cout << quotient(i,j); return 0; TESTPROG.EXE PROGRAM ABORTED OK 15
Simple Exception-Handling Example: Divide by Zero Next example Handle divide-by-zero errors Define new exception class» DivideByZeroException» Inherit from exception In division function» Test denominator» If zero, throw exception (throw object) In try block» Attempt to divide» Have enclosing catch block Catch DivideByZeroException objects 16
1 // Fig. 13.1: fig13_01.cpp 2 // A simple exception-handling example that checks for 3 // divide-by-zero exceptions. 4 #include <iostream> 5 6 using std::cout; 7 using std::cin; 8 using std::endl; 9 10 #include <exception> 11 12 using std::exception; 13 14 // DivideByZeroException objects should be thrown by functions 15 // upon detecting division-by-zero exceptions 16 class DivideByZeroException : public exception { 17 18 public: 19 20 // constructor specifies default error message 21 DivideByZeroException::DivideByZeroException() 22 : exception( "attempted to divide by zero" ) { 23 24 ; // end class DivideByZeroException 25 Define new exception class (inherit from exception). Pass a descriptive message to the constructor. Outline fig13_01.cpp (1 of 3) 2003 Prentice Hall, Inc. All rights reserved.
26 // perform division and throw DivideByZeroException object if 27 // divide-by-zero exception occurs 28 double quotient( int numerator, int denominator ) 29 { 30 // throw DivideByZeroException if trying to divide by zero 31 if ( denominator == 0 ) 32 throw DivideByZeroException(); // terminate function 33 34 // return division result 35 return static_cast< double >( numerator ) / denominator; 36 37 // end function quotient 38 39 int main() 40 { If the denominator is zero, throw a DivideByZeroException object. 41 int number1; // user-specified numerator 42 int number2; // user-specified denominator 43 double result; // result of division 44 45 cout << "Enter two integers (end-of-file to end): "; 46 Outline fig13_01.cpp (2 of 3) 2003 Prentice Hall, Inc. All rights reserved.
47 // enable user to enter two integers to divide 48 while ( cin >> number1 >> number2 ) { 49 50 // try block contains code that might throw exception 51 // and code that should not execute if an exception occurs 52 try { 53 result = quotient( number1, number2 ); 54 cout << "The quotient is: " << result << endl; 55 56 // end try 57 58 // exception handler handles a divide-by-zero exception 59 catch ( DivideByZeroException ÷byzeroexception ) { 60 cout << "Exception occurred: " 61 << dividebyzeroexception.what() << endl; 62 63 // end catch 64 Notice the structure of the try 65 cout << "\nenter two integers (end-of-file to end): "; 66 67 // end while 68 69 cout << endl; 70 71 return 0; // terminate normally 72 73 // end main and catch blocks. The catch block can catch DivideByZeroException objects, and print an error message. If no exception occurs, the catch block is skipped. Member function what returns the string describing the exception. Outline fig13_01.cpp (3 of 3) 2003 Prentice Hall, Inc. All rights reserved.
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 Outline fig13_01.cpp output (1 of 1) Enter two integers (end-of-file to end): ^Z 2003 Prentice Hall, Inc. All rights reserved.
Executing Code in a try block int main(){ cout << "Enter numerator and denominator: "; int numerator, denominator; cin >> numerator >> denominator; try { float answer = quotient(numerator, denominator); cout << "\n" << numerator << "/" << denominator << " = " << answer; catch (DivideByZeroError error) { //error handler cout << "ERROR: "; error.printmessage(); cout << endl; return 1; //terminate because of error return 0; //terminate normally Enter numerator and denominator: 3 4 3/4 = 0.75 21
...Executing Code in a try block main(){ cout << "Enter numerator and denominator: "; int numerator, denominator; cin >> numerator >> denominator; try { float answer = quotient(numerator, denominator); cout << "\n" << numerator << "/" << denominator << " = " << answer; catch (DivideByZeroError error) { //error handler cout << "ERROR: "; error.printmessage(); cout << endl; return 1; //terminate because of error return 0; //terminate normally Enter numerator and denominator: 3 0 ERROR: Divide by Zero 22
Throwing an Exception When a program encounters an error it throws an exception using throw anobject anobject can be any type of object and is called the exception object Exception will be caught by the closest exception handler (for the try block from which the exception was thrown) which matches the exception object type A temporary copy of the exception object is created and initialized, which in turn initializes the parameter in the exception handler The temporary object is destroyed when the exception handler completes execution 23
...Throwing an Exception class DivideByZeroError { public: DivideByZeroError() : message("divide by Zero") {cout << "construct: DivByZeroObject\n"; ~DivideByZeroError() {cout << "delete: DivByZeroObject\n"; void printmessage() const {cout << message; private: const char* message; ; Enter numerator and denominator: 3 0 construct: DivByZeroObject delete: DivByZeroObject ERROR: Divide by Zero delete: DivByZeroObject delete: DivByZeroObject 24
Constructors, Destructors and Exception Handling Error in constructor new fails; cannot allocate memory Cannot return a value - how to inform user?» Hope user examines object, notices errors» Set some global variable Good alternative: throw an exception» Destructors automatically called for member objects» Called for automatic variables in try block Can catch exceptions in destructor 25
Executing Code in a try block main(){ cout << "Enter numerator and denominator: "; int numerator, denominator; cin >> numerator >> denominator; try { float answer = quotient(numerator, denominator); cout << "\n" << numerator << "/" << denominator << " = " << answer; catch (DivideByZeroError error) { //error handler cout << "ERROR: "; error.printmessage(); cout << endl; return 1; //terminate because of error return 0; Enter numerator and denominator: 3 0 construct: DivByZeroObject delete: DivByZeroObject ERROR: Divide by Zero delete: DivByZeroObject delete: DivByZeroObject 26
Throwing an Exception Control exits the current try block and goes to appropriate catch handler The try blocks or functions which throw the exception can be deeply nested An exception can be thrown by code indirectly referenced from within a try block An exception terminates the block in which the exception occurred, and may cause program termination 27
Catching an Exception Exception handlers are contained within catch blocks catch(exception_object) { //exception handler code Catch handler specifies the type of object that it catches Exceptions which are not caught will cause program termination, by invoking function terminate, which in turn invokes abort 28
...Catching an Exception Specifying only the exception type is allowed, no object is passed, the type is simply used to select the appropriate handler catch(exception_type) { //exception handler code Specifying ellipses catches all exceptions catch(...) { //exception handler code 29
Unnamed Exception Handlers -only type specified try { float answer = quotient(numerator, denominator); cout << "\n"; cout << numerator << "/" << denominator << " = " << answer; catch (DivideByZeroError) { //type only error handler cout << "ERROR: DIVIDE_BY_ZERO\n"; return 1; //terminate because of error Enter numerator and denominator: 3 0 construct: DivByZeroObject delete: DivByZeroObject ERROR: DIVIDE_BY_ZERO delete: DivByZeroObject delete: DivByZeroObject 30
Catching all Exceptions try { float answer = quotient(numerator, denominator); cout << "\n"; cout << numerator << "/" << denominator << " = " << answer; catch (...) { //error handler cout << "ERROR: ERROR_IN_PROGRAM\n"; return 1; //terminate because of error One fewer destructors ran Enter numerator and denominator: 3 0 construct: DivByZeroObject delete: DivByZeroObject ERROR: ERROR_IN_PROGRAM delete: DivByZeroObject 31
... Throwing ints, doubles, etc main(){ int n = 5; double x = 5.0; try { cout << n << " factorial is " << factorial(n) <<"\n"; catch (int error) { //error handler cout << "\nerror INTEGER = " << error << "\n"; if (error < 0) cout << "...INT MUST BE GREATER THAN ZERO\n"; return 1; //terminate because of error catch (double error) { //error handler cout << "\nerror Double = " << error << "\n"; cout << "\n...argument CANNOT BE TYPE double\n"; return 1; //terminate because of error return 0; 5 factorial is 120 32
... Throwing ints, doubles, etc main(){ int n = -5; double x = 5.0; try { cout << n << " factorial is " << factorial(n) <<"\n"; catch (int error) { //error handler cout << "\nerror INTEGER = " << error << "\n"; if (error < 0) cout << "...INT MUST BE GREATER THAN ZERO\n"; return 1; //terminate because of error catch (double error) { //error handler cout << "\nerror Double = " << error << "\n"; cout << "\n...argument CANNOT BE TYPE double\n"; return 1; //terminate because of error return 0; ERROR INTEGER = -5...INT MUST BE GREATER THAN ZERO 33
... Throwing ints, doubles, etc main(){ int n = -5; double x = 5.0; try { cout << x << " factorial is " << factorial(x) <<"\n"; catch (int error) { //error handler cout << "\nerror INTEGER = " << error << "\n"; if (error < 0) cout << "...INT MUST BE GREATER THAN ZERO\n"; return 1; //terminate because of error catch (double error) { //error handler cout << "\nerror Double = " << error << "\n"; cout << "\n...argument CANNOT BE TYPE double\n"; return 1; //terminate because of error return 0; ERROR Double = 5...ARGUMENT CANNOT BE TYPE double 34
Throwing from Conditional Expressions main(){ int n = 5; double x = 5.0; try { n < 0? throw int(n) : cout << factorial(n); catch (int error) { //error handler cout << "\nerror INTEGER = " << error << "\n"; if (error < 0) cout << "...INT MUST BE GREATER THAN ZERO\n"; return 1; //terminate because of error catch (double error) { //error handler cout << "\nerror Double = " << error << "\n"; cout << "\n...argument CANNOT BE TYPE double\n"; return 1; //terminate because of error return 0; //terminate normally 120 35
...Throwing from Conditional Expressions main(){ int n = -5; double x = 5.0; try { n < 0? throw int(n) : cout << factorial(n); catch (int error) { //error handler cout << "\nerror INTEGER = " << error << "\n"; if (error < 0) cout << "...INT MUST BE GREATER THAN ZERO\n"; return 1; //terminate because of error catch (double error) { //error handler cout << "\nerror Double = " << error << "\n"; cout << "\n...argument CANNOT BE TYPE double\n"; return 1; //terminate because of error ERROR INTEGER = -5 return 0;...INT MUST BE GREATER THAN ZERO 36
...Throwing from Conditional Expressions main(){ int n = -5; double x = 5.0; try { n < 0? throw int(n) : throw double(x); catch... ERROR INTEGER = -5...INT MUST BE GREATER THAN ZERO main(){ int n = 5; double x = 5.0; try { n < 0? throw int(n) : throw double(x); catch... ERROR Double = 5...ARGUMENT CANNOT BE TYPE double 37
...Continuing After an Exception main(){ int n = -5; double x = 5.0; try { cout << n << " factorial is " << factorial(n) <<"\n"; catch (int error) { //error handler cout << "\nerror INTEGER = " << error << "\n"; if (error < 0) cout << "...INT MUST BE GREATER THAN ZERO\n"; return 1; //terminate because of an error catch (double error) { //error handler cout << "\nerror Double = " << error << "\n"; cout << "\n...argument CANNOT BE TYPE double\n"; return 1; //terminate because of error cout << "\n...processing continues...\n"; return 0; //terminate normally 38
Continuing After an Exception main(){ int n = -5; double x = 5.0; try { cout << n << " factorial is " << factorial(n) <<"\n"; catch (int error) { //error handler cout << "\nerror INTEGER = " << error << "\n"; if (error < 0) cout << "...INT MUST BE GREATER THAN ZERO\n"; return 1; //terminate because of an error catch (double error) { //error handler cout << "\nerror Double = " << error << "\n"; cout << "\n...argument CANNOT BE TYPE double\n"; return 1; //terminate because of error cout << "\n...processing continues...\n"; return 0; //terminate normally ERROR INTEGER = -5...INT MUST BE GREATER THAN ZERO 39
...Continuing After an Exception main(){ int n = -5; double x = 5.0; try { cout << n << " factorial is " << factorial(n) <<"\n"; catch (int error) { //error handler cout << "\nerror INTEGER = " << error << "\n"; if (error < 0) cout << "...INT MUST BE GREATER THAN ZERO\n"; return 0; //return indicating normal termination catch (double error) { //error handler cout << "\nerror Double = " << error << "\n"; cout << "\n...argument CANNOT BE TYPE double\n"; return 1; //terminate because of error Same Result cout << "\n...processing continues...\n"; return 0; //terminate normally ERROR INTEGER = -5...INT MUST BE GREATER THAN ZERO 40
...Continuing After an Exception (No Return Specified) main(){ int n = -5; double x = 5.0; try { cout << n << " factorial is " << factorial(n) <<"\n"; catch (int error) { //error handler cout << "\nerror INTEGER = " << error << "\n"; if (error < 0) cout << "...INT MUST BE GREATER THAN ZERO\n"; catch (double error) { //error handler cout << "\nerror Double = " << error << "\n"; cout << "\n...argument CANNOT BE TYPE double\n"; return 1; //terminate because of error cout << "\n...processing ERROR INTEGER continues...\n"; = -5 return 0; //terminate...int normally MUST BE GREATER THAN ZERO...processing continues... 41
Example //mismatch type, throw integer type //catch the double type... #include <iostream.h> void Funct(); int main() { try { Funct(); catch(double) { cerr<<"caught a double type..."<<endl; return 0; void Funct() { //3 is not a double but int throw 3; Output: Change the following statement throw 3; to throw 4.123; Output: 42
Processing Unexpected Exceptions unexpected() set_unexpected() terminate() set_terminate() abort() exit 43
Standard Exception Hierarchies 44
Standard Exceptions The C++ exception class serves as the base class for all exceptions thrown by certain expressions and by the Standard C++ Library. 45
46
47