|
|
Next the author inserts code to raise Objections at each point in the library
where an error may occur.
In the Stack library, an overflow error could occur in
the push()
routine, and underflow errors could occur
in the
pop()
and top()
routines.
When the library detects an error condition, e.g., someone trying to
push()
onto a full stack, it raises
an Objection with the
Objection::raise()
member function, e.g.,
Stack::overflow.raise()
. The value that
raise()
returns is dependent on the initial handler
which has been associated with the Objection by
the library user (see ``Instantiating
Objects With a Default Action''
and ``Objections for the Software Client'').
The library writer just needs to know
that one of two things should happen in the library
depending on the value returned from
raise()
.
If raise()
returns a 0, the default
action should take place.
If raise()
returns a non-zero integer, the recovery action
should take place.
raise()
will always return a 0 until
appoint()
or ignore()
changes this.
It is important that both the default action and recovery action
for each Objection be documented for the library user
(see ``Documenting Software with Objections'').
The Stack library author decides that the default action for raising either
the
Stack::underflow
or Stack::overflow
Objection is to abort the program with an
error message, using the following routine:
int error(const char* errmsg)
{
cerr << errmsg << "\ n";
abort();
return 0; // ignored but indicates
// what raise will return
}
The author also decides on the following recovery actions. If the client tries
to pop something from an empty stack,
pop()
returns MAXINT, which is defined to be the
largest integer on the machine.
If the client tries to get the top element from
an empty stack, top()
also returns MAXINT. If the
client tries to push()
something onto a full stack,
nothing happens; that is, the stack will be unchanged.
Given these default and recovery actions, the push()
,
pop()
, and top()
routines can be written as follows:
void Stack::push(int i)
{
if(size == SIZE) {
// error condition
if(Stack::overflow.raise()==0)
error("overflow error"); // default action
return; // recovery action
}
else
stack[size] = i;
size++;
}
int Stack::pop()
{
size--;
if(size < 0) {
// error condition
if(Stack::underflow.raise()==0)
error("underflow error");// default action
size = 0; // recovery action
return MAXINT;
}
else
return stack[size];
}
int Stack::top()
{
if(size == 0) {
// error condition
if(Stack::underflow.raise()==0)
error("underflow error");// default action
return MAXINT; // recovery action
}
else
return stack[size-1];
}
This is all the library author must do in order to set the stage for Objection handling.