exceptions. n programmers have traditionally ignored the proper dedication of attention to error...
Post on 21-Dec-2015
212 views
TRANSCRIPT
Exceptions
Exceptions
Programmers have traditionally ignored the proper dedication of attention to error handling
Enclosing code inside countless nested-ifs is not an attractive approach
This approach is not perfect either. It does minimize the attention you (the
programmer) have to give to errors once the appropriate infrastructure has been established.
Once again it has subtleties which require the programmer to be careful.
Should be used sparingly on MAJOR errors.
EXCEPTIONal circumstances
Determining WHEN to use exceptions is difficult and subjective.
Most authors tend to agree that they are to be used in exceptional circumstances– memory allocation problems– input file incorrectly formatted– dividing by zero– removing from an empty stack
In the first example, a rational number class will be examined. The primary errors here may not be exceptional but will serve to indicate the principles.
Current approaches include
Use the assert macro to display an error
char* newstring = char[stringlen+1];
assert(newstring != NULL);
-> Assertion failed: newstring != NULL;
Surrounding with an if if (newstring ==NULL) {...; exit(-1);}
..... For classes, you can install an error
handler as shown on p. 313 of Horstmann. (considered later)
THREE basic partsof exceptions
TRY - a block of code in which exceptions can occur
THROW - a call to an exception handler
CATCH - a routine to handle the problem
Example:try{ // code causes error .... throw Error1; // int }catch(int code){ ...// handle error }
try{ .. if(condition) throw ... }
catchhandler{ handle & stop or continue }
EXIT
Simple example
char inputint;
cin >> inputint;
try {
if (!isalpha(inputint))
throw (int) inputint;
...... // process normal char
}
catch(int errorval) {
inputint = FILLCHAR; }
// here ignore errorval
// continues execution
CLEARLY THIS WOULD BE HANDLED ANOTHER WAYBUT IT REPRESENTS A SIMPLE EXAMPLE
Multiple handlersare used in order and by
type
char inputint;
cin >> inputint;
try {
if (!isalpha(inputint))
throw (int) inputint;
else
throw inputint;
}
catch(int errorval) { // catch must immed follow try
cout << “Error int ” << errorval << endl; ... }
catch(char errorval) {
cout << “Good char ” << errorval << endl; }
5Error int 5
68Good char D
Flow control:throw or f(x) which throws
try { ...... throw or f(x) more statements in try } catch( ) { statements; exit or throw or neither } statements
f(x) { ...... throw ..; other statements in f(x); }
PROGRAM EXITS
To an enclosing nestedtry..catch.I.e. forward the errorto another handler.
more statements in try &other statements in f(x);MAY NOT EXECUTE!
Better example class Ratnl { private: long n; long d; public: Ratnl(long,long); Ratnl(long);};
Ratnl::Ratnl(long a,long b){if (a==0) throw(RatnlExcept(ZeroNum)); if (b==0) throw(RatnlExcept(ZeroDen));n=a; d=b; }
enum RatnlErr{enum RatnlErr{ ZeroNum, ZeroDen;};ZeroNum, ZeroDen;};
class RatnlExcept{class RatnlExcept{ RatnlError err;RatnlError err; public:public: RatnlExcept(RatnlErr c)RatnlExcept(RatnlErr c) { err = c;}{ err = c;} void Response()void Response() {switch (err){switch (err) case ZeroNumer:case ZeroNumer: cout << “0 Numer\n”; cout << “0 Numer\n”; break;break; case ZeroDenom:case ZeroDenom: cout << “0 Denom\n” }cout << “0 Denom\n” }};};
From WORX text The Beginner’s Guide to OOP Using C++by Romanovskaya, et all
The main routine
void main()
{ ....
try
{ Rational r(3,4);
Rational s(7,0);
cout << “Construction done!”;
}
catch (RatnlExcept & r)
{
r.response();
}
cout << “End of Program\n”;
}
OUTPUT:0 DenomEnd or Program
NOTE: The programmer decided to catch the error. Failure to catch is also a problem.
The throw statement
IMPLICIT THROW : You call a routine which throws an exception. If you have the call within a try block, the catch associated with the try containing the call may handle the error. (The main routine overhead)
– The called routine CAN catch the error.– If it does, it can also choose to throw the error
to an enclosing catch handler.» p. 318» rethrow same exception with no parameters
• throw;
EXPLICIT THROW: The try itself call throw. (Simple example overhead)
The catch function
Catch function must match parameters Catch functions are used from the
innermost to outermost try blocks. Note the try blocks are dynamically
defined Within a block, the order (matching) is the
physical order. The first parameter match found is the one
used (first). Catch can have (...) ellipses for parameters
– This handler matches ANY call
Catch can have NO type: only handles no parameter.
#include <iostream.h>
void main() { int t=5; try { if (t==5) throw 3; cout << "No error\n"; } catch (int z) {cout << "Value caught was " << z << endl;} cout << "Program done\n"; }
OUTPUT :Value caught was 3Program done
#include <iostream.h>
void main(){ int t=5; try { try { if (t==5) throw 3; cout << "No error\n"; } catch (int z) {cout << "Value caught was " << z << endl;} } catch (int x) {cout << "Value caught OUTER was " << x << endl;} cout << "Program done\n"; }
OUTPUT:Value caught was 3Program done
Catch function IS NOT CALLED !
void main(){ int t=5; try { try { if (t==5) throw 3; cout << "No error\n"; } catch (int z) {cout << "Value caught was " << z << endl; throw; // THROW IT TO OUTER HANDLER } } catch (int x) {cout << "Value caught OUTER was " << x << endl;} cout << "Program done\n"; }
OUTPUT:
Value caught was 3Value caught OUTER was 3Program done
void main(){ int t=5; try { try { if (t==5) throw 3; cout << "No error\n"; } catch (int z) {cout << "Value caught was " << z << endl; throw; // THROW IT TO OUTER HANDLER } catch (...) {cout << "In Catchall" << endl; throw;} } catch (int x) {cout << "Value caught OUTER was " << x << endl;} catch (...) {cout << "In SECOND Catchall" << endl;} cout << "Program done\n"; }
OUTPUT:Value caught was 3Value caught OUTER was 3Program done
NEITHER (...) functionsare used even with throw;Only one of the handlersis used at a level.
void main() { int t=5; try { try { if (t==5) throw 3; cout << "No error\n"; } catch (int z) {cout << "Value caught was " << z << endl; throw; } catch (...) {cout << "In Catchall" << endl; throw;} } catch (int x) {cout << "Value caught OUTER was " << x << endl; throw; // THROW IT TO OUTER HANDLER } catch (...) {cout << "In SECOND Catchall" << endl;} cout << "Program done\n"; }
OUTPUT:Value caught was 3Value caught OUTER was 3Abnormal program termination
The last throw couldNOT be caught andresulted in termination!
catch(...)
Always use catch(...) last
try
{ ---------- }
catch (...)
{ -------- }
catch ( int x )
{ -------- } The last handler will never be used
because the first handler will always catch the exception.
Control over who throws
Any exception thrown but not caught results in abnormal program termination!
You want knowledge (minimally) and control (optimally) over who throws.
resulttype f(parameters) throw (throwlist);
Ratnl f(long x, long y) throw (RatnlExcept);
This determines what exceptions can be thrown by this function!... a throwlistAny other throw results in program termination.
throw()as a throwlist intercepts the throw and does not allow it outside the function,but short-circuits straight to program termination, unlessthe function ITSELF has acatch for the throw.
Types of exceptions If an exception occurs which is not listed in the throw list ->
UNEXPECTED EXCEPTION– c++ has a function unexpected() which handles the error.
– you can redefine it.
» Yours-> void myunxp();
{ ... ; terminate(); // called by system one}
» call -> set_unexpected(myunxp); If no matching handler is found -> UNHANDLED EXCEPTION
– Normally calls terminate(); as shown above
– redefine by
» call -> set_terminate(myterminate);– your terminate() should call either
»exit() or abort()
Constructors and Destructors
If the code is skipped in a try block, what about the destructors?
When an exception is thrown inside a try block, the destructor for each and every object created in the try block is called before the catch handler gets control.
class Ratnl{ ... ~Ratnl() // destructor { cout << “Rat done!” << n << ‘/’ << d << ‘\n’;} };
void main() { try { Ratnl r(3,5); Ratnl s(2,0); } ... }
OUTPUT:...Rat done 3/5
Where should try begin/end?
Considering the constructor/destructor issue:
Consider the group of items which are involved in an operation
Declare objects in the try block when possible.
When the operation fails, destructors are automatically called. Some can, others can’t.fs istream;
fs.open(“datafile”);g(fs); // causes exceptionfs.close(); // not called
fs.open(“datafile”);try { Employee e; f(fs);}catch(...) { fs.close(); throw; }fs.close();
NOTE: in this example, fs COULD be placed inside
Catch routines with references to base/derived
classes
Given a base class B and derived class D: Assume that each class has a routine
defined for you to use as a catch routine (part of the class).
catch ( B& b)
{ ..... }
catch ( D& d)
{ ..... } Can the second ever be reached?
NO. A B reference will use the first
A D reference will be converted to a B reference
A Design Strategy
When designing your own class libraries provide the programmer an opportunity to supply a handler.
Here I use the term handler to indicate routine which throws not the routine which catches.
P.313 Stack shows how to– define a default handler– let the programmer set their own handler– let the programmer reset the handler to the original– user version can only access public info
The default handler can throw exceptions The programmer substituted handler can
avoid throwing the error.
Static Member Functions
Static member functions in Stack:
Function is for the whole class “this” is not available only static data members and static
functions can be accessed
Design Suggestions
Don’t catch it if you can’t handle it. Don’t use exceptions for simple errors
easily handled with direct code. You want to continue if possible. Avoid
throwing if you can continue from where you are.
Give users of libraries some control over handlers
Package items in the try section to be in objects which have properly defined destructors so that they are properly disposed in the event of exceptions thrown.