// Exceptor.cpp // CSC 601 - Fall 2001 (revised Fall 2002) - Kirby // ------------------------------------------------- // // A demonstration of basic exception handling. // Trace information is dribbled to cout to show what's happening. // // Note the OO hierarchy: MyException < invalid_argument < logic_error < exception. // Also note the issue of lifetime of exception objects. #include #include #include using namespace std ; struct SomeClass // This is here so we can show that local auto dtors are called upon stack unwinding. { SomeClass() throw() {} ~SomeClass() throw() { cout << "SomeClass dtor" << endl ; } } ; struct MyException : public invalid_argument // A homemade exception class. // This is here so we can see when the ctors and dtor are really called. { MyException( const string &s ) : invalid_argument ( s ) { cout << "MyException ctor" << endl ; } MyException( const MyException& e ) : invalid_argument( e.what() ) { cout << "MyException copy-ctor" << endl ; } ~MyException() { cout << "MyException dtor" << endl ; } } ; void recur( int n ) throw ( invalid_argument ) // A recursive function making the point that exceptions are // thrown "down" the stack, not "across" the code. { cout << "recur( " << n << ")" << endl ; SomeClass c ; if ( n < 0 ) { throw ( MyException( "Negative argument" ) ); // TRY REPLACING THIS LINE WITH THE FOLLOWING TWO. WHAT'S THE DIFFERENCE? // MyException e( "Negative argument!" ) ; // throw ( e ) ; } if ( n == 0 ) cout << "...bottom!" << endl ; else recur( n-2 ) ; cout << "Return from recur( " << n << ")" << endl ; } void play( int n ) throw ( logic_error ) // Goes bad when a negative or odd number is passed in. { cout << endl << "CALL play( " << n << " )..." << endl; recur( n ) ; cout << "RETURN from play( " << n << " )." << endl; } void starter() throw () // Try to cause trouble. { cout << endl << "CALL starter()..." << endl; try { play( 4 ) ; // should be okay play( 3 ) ; // asking for trouble } catch ( logic_error& e ) { cout << "CAUGHT: " << e.what() << endl ; } cout << endl << "RETURN from starter()." << endl; } int main() { starter() ; cout << "Natural end." << endl ; return 0 ; }