7.1 Throwing an Exception
The exception handling facility consists of two primary components: the recognition and raising of an exception and the eventual handling of the exception. Typically, an exception is raised and handled within various member or nonmember functions. After an exception is raised, normal program execution is suspended. The exception handling facility searches for a portion of the program that is capable of handling the raised exception. After the exception has been handled, program execution resumes in the portion of the program that has handled the exception.
In C++, we raise an exception by using the
throw expression:
inline void Triangular_iterator::
check_integrity()
{
if ( _index > Triangular::_max_elems )
throw iterator_overflow( _index,
Triangular::_max_elems );
if ( _index > Triangular::_elems.size() )
Triangular::gen_elements( _index );
}
The throw expression looks somewhat like a function call. In this example, if _index is greater than _max_elems, an exception object of type iterator_overflow is thrown. The second if statement is never executed, and control does not return to this point in the program after the exception is handled. If _index is less than or equal to _max_elems, no exception is raised, and the program executes as we expect.
What is the exception that gets thrown? An
exception is an object of some type. A simple exception object might be an integer or a string:
throw 42;
throw "panic: no buffer!";
Most often, thrown exceptions are class objects of an explicitly provided exception class or exception class hierarchy. For example, here is the definition of the iterator_overflow class:
class iterator_overflow{
public:
iterator_overflow( int index, int max )
: _index( index ), _max( max ) {}
int index() { return _index; }
int max() { return _max; }
void what_happened( ostream &os = cerr ) {
os << "Internal error: current index "
<< _index << " exceeds maximum bound: "
<< _max;
}
private:
int _index;
int _max;
};
There is nothing exceptional about the class. We simply define it to store whatever data we wish to carry across program call points to communicate the nature of the raised exception.
The throw expression of our example directly invokes the two-parameter constructor. Alternatively, we can throw an explicit class
object:
if ( _index > Triangular::_max_elems ){
iterator_overflow ex( _index, Triangular::_max_elems );
throw ex;
}
|