Q:

When and how to catch exceptions

I am working on a code-base with a bunch of developers who aren't primarily Computer Science or Software Engineering (Mostly Computer Engineering)
I am looking for a good article about when exceptions should be caught and when one should try to recover from them.  I found an article a while ago that I thought explained things well, but google isn't helping me find it again.
We are developing in C++.  Links to articles are an acceptable form of answer, as are summaries with pointers.  I'm trying to teach here, so tutorial format would be good.  As would something that was written to be accessible to non-software engineers.  Thanks.

A:

Herb Sutter has an excellent article that may be useful to you. It does not answer your specific question (when/how to catch) but does give a general overview and guidelines for handling exceptional conditions.
I've copied his summary here verbatim

Distinguish between errors and
  nonerrors. A failure is an error if
  and only if it violates a function's
  ability to meet its callees'
  preconditions, to establish its own
  postconditions, or to reestablish an
  invariant it shares responsibility for
  maintaining. Everything else is not an
  error.
Ensure that errors always leave your
  program in a valid state; this is the
  basic guarantee. Beware of
  invariant-destroying errors
  (including, but not limited to,
  leaks), which are just plain bugs.
Prefer to additionally guarantee that
  either the final state is either the
  original state (if there was an error,
  the operation was rolled back) or
  intended target state (if there was no
  error, the operation was committed);
  this is the strong guarantee.
Prefer to additionally guarantee that
  the operation can never fail. Although
  this is not possible for most
  functions, it is required for
  functions such as destructors and
  deallocation functions.
Finally, prefer to use exceptions
  instead of error codes to report
  errors. Use error codes only when
  exceptions cannot be used (when you
  don't control all possible calling
  code and can't guarantee it will be
  written in C++ and compiled using the
  same compiler and compatible compile
  options), and for conditions that are
  not errors.

