Exception Handling
Exception Handling
a try block. If an exception occurs within the try block, it is thrown(using throw). The exception is caught, using catch, and processed. Catch immediately follows the try statement in which the exception was thrown. The general form is: try { // try block } catch(type1 arg) { // catch block } catch(type2 arg) { // catch block } catch(type3 arg) { // catch block } . . catch(typeN arg){ // catch block }
C++ Exception handling is built upon three keywords: try, catch, and throw. Program statements that we want to monitor for exceptions are contained in
an exception is thrown, it is caught by its corresponding catch statement, which processes the exception. There can be more than one catch statement associated with a try. Which catch statement is used is determined by the type of the exception. When an exception is caught, arg will receive its value. Any type of data may be caught, including classes that we create. If no exception is thrown then no catch statement is executed. The general form of the throw statement is shown here: throw exception; Throw generates the exception specified by exception. If we throw an exception for which there is no applicable catch statement, an abnormal program termination may occur. Ex. #include<iostream.h> void main() { cout<<Start\n;
When
try{ cout<<Inside try block\n; throw 100; cout<<This will not execute; } catch(int i) { cout<<Caught an exceptionvalue is:; cout<<i<<\n; } cout<<End; } o/p Start Inside try block Caught an exceptionvalue is:100 End If we change the type in the catch statement to double, the exception will not be caught and abnormal termination will occur.
#include<iostream.h> void main() { cout<<Start\n; try{ cout<<Inside try block\n; throw 100; cout<<This will not execute; } catch(double i) { cout<<Caught an exceptionvalue is:; cout<<i<<\n; } cout<<End; } o/p Start Inside try block Abnormal program termination
exception can be thrown from outside the try block as long as it is thrown by a function that is called from within try block. #include<iostream.h> void Xtest(int test) { cout<<Inside Xtest, test is:<<test<<\n; if(test) throw test; } void main() { cout<<start\n; try { // start a try block cout<<Inside try block\n; Xtest(0); Xtest(1); Xtest(2); } catch(int i) { cout<<Caught an exceptionvalue is:; cout<<i<<\n; } cout<<End; } o/p Start Inside try block Inside Xtest, test is:0 Inside Xtest, test is:1 Caught an exceptionvalue is:1 End
The
try block can be localized to a function. #include<iostream.h> void Xhandler(int test) { try{ if(test) throw test; } catch( int i) { cout<<Caught Exception#:<<i<<\n; } } void main() { cout<<Start\n; Xhandler(1); Xhandler(2); Xhandler(0); Xhandler(3); cout<<End; } o/p Start Caught Exception#:1 Caught Exception#:2 Caught Exception#:3 End
The code associated with a Catching Class Types: An exception can be of any Ex.
catch statement will be executed only if it catches an exception. type, including class types that we create.
#include<iostream.h> #include<cstring> class MyException { public: char str_what[80]; int what; MyException() { *str_what=0; what=0;} MyException(char *s, int e){ strcpy(str_what,s); what=e; } }; void main() { int i; try { cout<<Enter a positive number:; cin>>i; if(i<0) throw MyException(Not Positive,i); } catch(MyException e){ cout<<e.str_what<<:; cout<<e.what<<\n; }
try.
Handling Derived-Class Exceptions Derivedneed to be careful how we order our catch statements when trying to catch exception types that involve base and derived classes because a catch clause for a base class will also match any class derived from that base. Thus, if we want to catch exceptions of both a base class type and a derived class type, put the derived class first in the catch sequence. If we dont do this, the base class catch will also catch all derived classes. Ex. #include<iostream.h> class B{ }; class D:public B { }; void main() { D derived; try { throw derived; } catch(B b) { cout<<Caught a base class.\n; } catch(D d) { cout<<This wont execute.\n; } }
We
Here, because derived is an object that has B as a base class, it will be caught by the first catch clause and the second clause will never execute. Exception Handling Options: Catching All Exceptions: In some situation we want an exception handler to catch all exceptions instead of just a certain type. This is accomplished by using the form of catch like: catch(){ // process all exceptions } Ex. #include<iostream.h> void Xhandler(int test) { try{ if(test==0) throw test; // throw int if(test==1) throw a;// throw char if(test==2) throw 123.23;// throw double } catch() { // catch all exceptions cout<<Caught One!\n; } } void main() { cout<<Start\n; Xhandler(0); Xhandler(1); Xhandler(2); cout<<End; } o/p Start Caught One! Caught One! Caught One! End
One very good use for catch() is as the last catch of It provides a useful default or catch all statement. Ex.
a cluster of catches.
#include<iostream.h> void Xhandler(int test) { try{ if(test==0) throw test; // throw int if(test==1) throw a;// throw char if(test==2) throw 123.23;// throw double } catch( int i) { // catch an int exception cout<<Caught an integer\n; } catch() { // catch all exceptions cout<<Caught One!\n; } } void main() { cout<<Start\n; Xhandler(0); Xhandler(1); Xhandler(2); cout<<End; }
Restricting Exceptions
can restrict the type of exceptions that a function can throw outside of itself. We can also prevent a function from throwing any exceptions whatsoever. To accomplish these restrictions, we must add a throw clause to a function definition. The general form is: ret-type func-name(arg-list)throw(type-list) { // } Here only those data types contained in the comma-separated typelist may be thrown by the function. Throwing any other type of expression will cause abnormal program termination. If we dont want a function to be able to throw any exceptions, then use an empty list. Attempting to throw an exception that is not supported by a function will cause the standard library function unexpected() to be called. By default, this causes abort() to be called, which causes abnormal program termination.
We
Ex.
#include<iostream.h> void Xhandler(int test) throw(int, char, double) { if(test==0) throw test; // throw int if(test==1) throw a; // throw char if(test==2) throw 123.23; // throw double } void main() { cout<<start\n; try{ Xhandler(0); } catch(int i) { cout<<Caught an integer\n; } catch(char c) { cout<<Caught char\n; } catch(double d) { cout<<Caught double\n; } cout<<end; }
Rethrowing an Exception
we wish to rethrow an expression from within an exception handler, we may do so by calling throw, by itself, with no exception. This causes the current exception to be passed on to an outer try/catch sequence. The most likely reason for doing so is to allow multiple handlers access to the exception. An exception can only be rethrown from within a catch block( or from any function called from within that block). When we rethrow an exception, it will not be recaught by the same catch statement. It will propagate outward to the next catch statement. Ex. #include<iostream.h> void Xhandler() { try{ throw hello; // throw a char * } catch(const char *) { // catch a char * cout<<Caught char* inside Xhandler\n; throw; // rethrow char * out of function } }
If
void main() { cout<<Start\n; try { Xhandler(); } catch(const char *) { cout<<Caught char * inside main\n; } cout<<End; } o/p: Start Caught char * inside Xhandler Caught char * inside main End