Exception handling allows us to deal with unexpected situations that may occur in a
program. When a function encounters a situation that it cannot recover from it can generate
an exception to signal to the caller that the function has failed.
This is done using the throw keyword followed by whatever it is we want to signal. When
this statement is reached the method will stop executing and the exception will propagate
up to the caller where we can catch it, using a try-catch statement.
This statement consists of a try block containing code that may cause exceptions and one or
more catch clauses to handle them. In this case we throw an integer and so we need to
include one catch block that handles this type of exception. The thrown expression will
get passed as an argument to this exception handler where it can be used to determine
what has gone wrong with the function. Note that when the exception has been handled the
execution will then continue running after the try-catch blocks and not after the throw
statement.
An exception handler can catch a thrown expression either by value, reference, or pointer. However,
catching by value should be avoided since this causes an extra copy to be made. Catching
by reference is generally preferable. If the code in the try block can throw more types
of exceptions we would need to add more catch clauses to handle them. Keep in mind that
only the handler that matches the thrown expression will be executed. To catch all types of exceptions
we can use an ellipsis (...) as the parameter of catch. This default handler must be placed
as the last catch statement since no handler placed after it would ever be executed.
If an exception handler is not able to recover from an exception we can then re-throw it
using only the throw keyword to pass it along to an external try-catch block. Be careful
though, because if an exception is never caught the program will terminate with a run-time
error.
Functions are by default allowed to throw exceptions of any type. To specify the exception
types that a function may throw we can append the throw keyword to the function declaration
followed by a comma separated list of the allowed types, if any, enclosed in parenthesis.
This exception specification is very different from the one used in Java and overall there
is very little reason to specify exceptions in C++. The compiler will not enforce the
specified exceptions in any way and it will not be able to make any optimizations because
of them.
As previously mentioned, any data type can be thrown in C++, but the standard library
does provide a base class called exception which is specifically designed to declare
objects to be thrown. It is defined in the exception header file and is located under
the std namespace. As seen here, it can be constructed with a char sequence that becomes
the exception’s description. When we catch this exception we can use the object’s function
"what" to retrieve the description.