External errors are due to events beyond the scope of the program. As we mentioned in the introduction, any non-trivial program should be prepared to recover from an external error. In general, external errors are:
Not easily predicted in advance;
Encountered at more abstract levels;
Not costly to detect;
Detected in both the production and the debug versions of the library.
Examples of external errors would include: an attempt to set a bad date, such as 31 June 1992; an attempt to invert a singular matrix; a stream write error; being out of memory. Tools.h++ would respond to these by throwing an exception inheriting from RWExternalErr, or providing a test for object validity.
External errors may be run time errors. In an object-oriented environment, run time errors frequently show up as an attempt to set an object into an invalid state, perhaps as a result of invalid user input. The example given above, initializing a date object with the nonexistent date 31 June 1992, is an external run time error.
External errors often take the form of exceptions thrown by the operating system. Tools.h++ takes responsibility for detecting these exceptions and recovering the resources it has acquired; it will close files and restore heap memory. As the user, however, you are responsible for all resources acquired by code external to the Tools.h++ library during these kinds of exceptions. Generally, Tools.h++ assumes that these exceptions will not be thrown during memory-related C library calls such as memcpy. Tools.h++ make every effort to detect throws which occur during operations on Tools.h++ objects or user-defined objects.
In theory, the Tools.h++ response to an external error is to throw an exception, or to provide a test for object validity. It should never abort the program. In practice, however, some compilers do not handle exceptions, so Tools.h++ provides an opportunity to recover in an error handler, or to test for a status value. Here is an example of using the isValid function to validate user input:
RWDate date; while (1) { cout << "Give a date: "; cin >> date; if (date.isValid()) break; cout << "You entered a bad date; try again\n"; }