CPSC 427: Object-Oriented Programming
Michael J. Fischer
Exceptions
Exceptions
An exception is an event that prevents normal continuation.
Exceptions may be due to program errors or data errors, but they may also be due to external events:
How to respond to different kinds of exceptions is application-dependent.
Exception handling
When an exception occurs, a program has several options:
Problem: Exceptions are often detected at a low level of the code.
Knowledge of how to respond resides at a higher level.
C-style solution using status returns
The C library functions generally report exceptions by returning status
values or error codes.
Advantages: How to handle exception is delegated to the caller.
Disadvantages:
C++ exception mechanism
C++ exception mechanism is a means for a low-level routine to report an
exception directly to a higher-level routine.
This separates exception-handling code from normal processing
code.
An exception is reported using the keyword throw.
An exception is handled in a catch block.
Each routine in the chain between the reporter and the handler is exited cleanly, with all destructors called as expected.
Thowing an Exception
Throwing
an
exception
(demo
19a-Exceptions)
throw is followed by an exception value.
Exceptions are usually objects of a user-defined exception type.
Example:
throw AgeError("Age can’t be negative");
Exception class definition:
Catching an Exception
Catching an exception A try region defines a section of code to be monitored for exceptions.
Immediately following are catch blocks for handling the exceptions.
The catch parameter should generally be a reference parameter as in this example.
What
kind
of
object
should
an
exception
throw?
catch filters the kinds of exceptions it will catch according to the type
of object thrown.
For this reason, each kind of exception should throw it’s own type of
object.
That way, an exception handler appropriate to that kind of exception can
catch it and process it appropriately.
While it may be tempting to throw a string that describes the error
condition, it is difficult to process such an object except by printing it
out and aborting (like Fatal()).
Properly used, exceptions are much more powerful than that.
Example: Stack template throws exception
It is an error to pop an empty stack.
We have given several sample stack implementations. Here’s what they each do when attemption to pop an empty stack:
Demo | Action on empty pop error |
08-Brackets | undefined (programmer must avoid) |
19-Virtual/linear.cpp | return nullptr |
19b-Exceptions-stack | throw exception |
Demo 19b-Exceptions-stack gives one way to handle an empty pop error using throw.
Polymorphic exception classes
A catch clause can catch polymorphic exception objects.
Demo 19c-Exceptions-cards‘w shows how this can be used to
provide finer error control.
The base exception class Bad has a virtual print function. Derived from
it are two classes BadSuit and BadSpot.
The catch clause catch (bad& bs) {...} will catch all three kinds of
errors: bad suit, bad spot, and bad both.
These are errors that can arise while reading a playing card from the user.
Standard exception class
The standard C++ library provides a polymorphic base class std::exception from which all exceptions thrown by components of the C++ Standard library are derived.
These are:
exception | description |
bad_alloc | thrown by new on allocation failure |
bad_cast | thrown by a failed dynamic_cast |
bad_exception | thrown when an exception type doesn’t match any catch |
bad_typeid | thrown by typeid |
ios_base::failure | thrown by functions in the iostream library |
(from http://www.cplusplus.com/doc/tutorial/exceptions/)
Catching standard exceptions
Class std::exception contains a virtual function Because the base class is polymorphic, it is possible to write a single
catch handler that will catch all derived exception objects. Example:
Deriving
your
own
exception
classes
from
std::exception
Multiple
catch
blocks
{
cerr << "exception caught: " << e.what() << endl;
}
#include <exception>
using namespace std;
class myexception: public exception {
virtual const char* what() const throw()
{ return "My exception happened"; }
} myex; // declares class and instantiates it
int main () {
try {
throw myex;
}
catch (exception& e) {
cout << e.what() << endl;
}
return 0;
}