Exceptions, Catch, and Throw
So far we're been developing code in Pleasantville, a wonderful
place where nothing ever, ever goes wrong.
Every library call
succeeds, users never enter incorrect data, and resources are
plentiful and cheap. Well, that's about to change. Welcome to the
real world!
In the real world, errors happen. Good programs (and programmers)
anticipate them and arrange to handle them gracefully. This isn't
always as easy as it might be. Often the code that detects an error
does not have the context to know what to do about it. For example,
attempting to open a file that doesn't exist is acceptable in some
circumstances and is a fatal error at other times. What's your
file-handling module to do?
The traditional approach is to use return codes. The
open
method returns some specific value to say it failed. This value
is then propagated back through the layers of calling routines
until someone wants to take responsibility for it.
The problem with this approach is that managing all these error codes
can be a pain. If a function calls
open
, then
read
,
and finally
close
, and each can return an error indication, how
can the function distinguish these error codes in the value it returns
to
its caller?
To a large extent, exceptions solve this problem. Exceptions let you
package up information about an error into an object. That exception
object is then propagated back up the calling stack automatically
until the runtime system finds code that explicitly declares that it
knows how to handle that type of exception.