class Matherr { } class Overflow : public Matherr {} try { f();do some arithmetic
} catch (Overflow) {// handle Overflow
} catch (Matherr) {// handle non-Overflow Matherr
}
template< class T, class X > inline void Assert(T expr, X x) { if (!NDEBUG) if (!expr) throw x; }
Interventions are familiar from daily computing practice in the form of interrupts, such as are used to kill a process. Under Unix, an interrupt is implemented as a signal that may be associated with a handler. The interrupt handler usually invokes the exit function.
Exceptions, on the other hand, are not (yet) familiar to most programmers and are only supported by a few languages.
One of the languages supporting exceptions is Eiffel.
In Eiffel, exceptions are closely linked with the
notion of contracts.
Abnormal events occur whenever a contract is violated,
that is when either a pre-condition, post-condition
or invariant is not satisfied.
For each of these cases an exception handler may be specified
in the class defining the object for which an exception is raised.
The way in which abnormal events are dealt with in Eiffel
conforms to what is called the resumption model
in
Exceptions are part of the language definition of C++, but not many of the available compilers provide support for exceptions. The declaration of exceptions conforms to the definition of classes. For example, slide 6-abnormal declares a Matherr and an Overflow exception, which is publicly derived from Matherr. Obviously, the advantage of employing the class mechanism is that inheritance may be used to organize exceptions in groups. The most specific exception may then be tested for first, as in the catch statements following the try block in slide 6-abnormal. As the example shows, exception handling is activated by wrapping a group of statements or function calls in a try block. Whenever a failure occurs, the exception handlers declared by the subsequent catch statements will be tried to do something about it.
An exception may be raised by means of a throw statement as illustrated for the Assert function. The Assert function mimics the behavior of the assert macro, but in addition allows us to raise an explicit exception such as BadArgs or Invariant (provided these are defined as exceptions).
In contrast to Eiffel,
which allows for resuming the computation
after the occurrence of an exception,
C++ supports only termination semantics
for exceptions, which results in terminating the function call
that caused the exception.
The main reason to adopt termination semantics
is (according to
Lacking adequate language support, both exceptions and interventions may be simulated, respectively by setting a global flag which is tested after the operation and by adding intervention routine parameters to function definitions. However, such simulations are tedious and error-prone to implement and, moreover, violate encapsulation and endanger extensibility.