mirror of
https://gitlab.com/fbb-git/cppannotations
synced 2024-11-16 07:48:44 +01:00
6881bc3814
Annotations. The branches and tags directory are empty, since I couldn't svnadmin import a repostitory dump. Many earlier versions exist, though, and if you want the full archive, just let me know and I'll send you the svnadmin dump of my full C++ Annotations archive. Frank B. Brokken <f.b.brokken@rug.nl> git-svn-id: https://cppannotations.svn.sourceforge.net/svnroot/cppannotations/trunk@3 f6dd340e-d3f9-0310-b409-bdd246841980
97 lines
4.4 KiB
Text
97 lines
4.4 KiB
Text
Situations may occur in which it is required to inspect a thrown
|
|
exception. Then, depending on the nature of the received exception, the
|
|
program may continue its normal operation, or a serious event took place,
|
|
requiring a more drastic reaction by the program. In a server-client situation
|
|
the client may enter requests to the server into a queue. Every request placed
|
|
in the queue is normally answered by the server, telling the client that the
|
|
request was successfully completed, or that some sort of error has
|
|
occurred. Actually, the server may have died, and the client should be able to
|
|
discover this calamity, by not waiting indefinitely for the server to reply.
|
|
|
|
In this situation an intermediate i(exception handler) is called for. A thrown
|
|
exception is first inspected at the middle level. If possible it is processed
|
|
there. If it is not possible to process the exception at the middle level, it
|
|
is passed on, unaltered, to a more superficial level, where the really tough
|
|
exceptions are handled.
|
|
|
|
By placing an hi(throw: empty) em(empty) tt(throw) statement in the code
|
|
handling an exception the received exception is passed on to the next level
|
|
that might be able to process that particular type of exception.
|
|
|
|
In our server-client situation a function
|
|
verb(
|
|
initialExceptionHandler(char *exception)
|
|
)
|
|
could be designed to do so. The received message is inspected. If it's a
|
|
simple message it's processed, otherwise the exception is passed on to an
|
|
outer level. The implementation of tt(initialExceptionHandler()) shows the
|
|
empty tt(throw) statement:
|
|
verb(
|
|
void initialExceptionHandler(char *exception)
|
|
{
|
|
if (!plainMessage(exception))
|
|
throw;
|
|
|
|
handleTheMessage(exception);
|
|
}
|
|
)
|
|
As we will see below (section ref(EXCEPTIONCATCH)), the empty tt(throw)
|
|
statement passes on the exception received in a tt(catch)-block. Therefore, a
|
|
function like tt(initialExceptionHandler()) can be used for a variety of
|
|
thrown exceptions, as long as the argument used with
|
|
tt(initialExceptionHandler()) is compatible with the nature of the received
|
|
exception.
|
|
|
|
Does this sound intriguing? Then try to follow the next example, which jumps
|
|
slightly ahead to the topics covered in chapter ref(POLYMORPHISM). The next
|
|
example may be skipped, though, without loss of continuity.
|
|
|
|
We can now state that a i(basic exception handling) class can be constructed
|
|
from which specific exceptions are derived. Suppose we have a class
|
|
tt(Exception), containing a member function tt(ExceptionType
|
|
Exception::severity()). This member function tells us (little wonder!) the
|
|
severity of a thrown exception. It might be tt(Message, Warning, Mistake,
|
|
Error) or tt(Fatal). Furthermore, depending on the severity, a thrown
|
|
exception may contain less or more information, somehow processed by a
|
|
function tt(process()). In addition to this, all exceptions have a plain-text
|
|
producing member function, e.g., ti(toString()), telling us a bit more about
|
|
the nature of the generated exception.
|
|
|
|
Using i(polymorphism), tt(process()) can be made to behave differently,
|
|
depending on the nature of a thrown exception, when called through a basic
|
|
tt(Exception) pointer or reference.
|
|
|
|
In this case, a program may throw any of these five types of exceptions. Let's
|
|
assume that the tt(Message) and tt(Warning) exceptions are processable by our
|
|
tt(initialExceptionHandler()). Then its code would become:
|
|
verb(
|
|
void initialExceptionHandler(Exception const *e)
|
|
{
|
|
cout << e->toString() << endl; // show the plain-text information
|
|
|
|
if
|
|
(
|
|
e->severity() != ExceptionWarning
|
|
&&
|
|
e->severity() != ExceptionMessage
|
|
)
|
|
throw; // Pass on other types of Exceptions
|
|
|
|
e->process(); // Process a message or a warning
|
|
delete e;
|
|
}
|
|
)
|
|
Due to polymorphism (see chapter ref(POLYMORPHISM)), tt(e->process()) will
|
|
either process a tt(Message) or a tt(Warning). Thrown exceptions are generated
|
|
as follows:
|
|
verb(
|
|
throw new Message(<arguments>);
|
|
throw new Warning(<arguments>);
|
|
throw new Mistake(<arguments>);
|
|
throw new Error(<arguments>);
|
|
throw new Fatal(<arguments>);
|
|
)
|
|
All of these exceptions are processable by our
|
|
tt(initialExceptionHandler()), which may decide to pass exceptions upward for
|
|
further processing or to process exceptions itself. The polymorphic exception
|
|
class is developed further in section ref(POLYMORPHEXCEPTION).
|