A program catches an exception with an
A try
The easiest way to see how these three elements fit together is to look at a short example, such as the one in Listing 15.9.
Listing 15.9. error3.cpp
// error3.cpp -- using an exception
#include
double hmean(double a, double b);
int main()
{
double x, y, z;
std::cout << "Enter two numbers: ";
while (std::cin >> x >> y)
{
try { // start of try block
z = hmean(x,y);
} // end of try block
catch (const char * s) // start of exception handler
{
std::cout << s << std::endl;
std::cout << "Enter a new pair of numbers: ";
continue;
} // end of handler
std::cout << "Harmonic mean of " << x << " and " << y
<< " is " << z << std::endl;
std::cout << "Enter next set of numbers : ";
}
std::cout << "Bye!\n";
return 0;
}
double hmean(double a, double b)
{
if (a == -b)
throw "bad hmean() arguments: a = -b not allowed";
return 2.0 * a * b / (a + b);
}
Here’s a sample run of the program in Listing 15.9:
Enter two numbers: 3 6
Harmonic mean of 3 and 6 is 4
Enter next set of numbers : 10 -10
bad hmean() arguments: a = -b not allowed
Enter a new pair of numbers: 1 19
Harmonic mean of 1 and 19 is 1.9
Enter next set of numbers : q
Bye!
Program Notes
The try block in Listing 15.9 looks like this:
try { // start of try block
z = hmean(x,y);
} // end of try block
If any statement in this block leads to an exception being thrown, the catch blocks after this block will handle the exception. If the program calls hmean() somewhere else outside this (and any other) try block, it won’t have the opportunity to handle an exception.
Throwing an exception looks like this:
if (a == -b)
throw "bad hmean() arguments: a = -b not allowed";
In this case, the thrown exception is the string "bad hmean() arguments: a = -b not allowed". The exception type can be a string, as in this case, or other C++ types. A class type is the usual choice, as later examples in this chapter illustrate.
Executing the throw is a bit like executing a return statement in that it terminates function execution. However, instead of returning control to the calling program, a throw causes a program to back up through the sequence of current function calls until it finds the function that contains the try block. In Listing 15.9, that function is the same as the calling function. Soon you’ll see an example involving backing up more than one function. Meanwhile, in this case, the throw passes program control back to main(). There, the program looks for an exception handler (following the try block) that matches the type of exception thrown.
The handler, or catch block, looks like this:
catch (char * s) // start of exception handler
{
std::cout << s << std::endl;
sdt::cout << "Enter a new pair of numbers: ";
continue;
} // end of handler
The catch block looks a bit like a function definition, but it’s not. The keyword catch identifies this as a handler, and char * s means that this handler matches a thrown exception that is a string. This declaration of s acts much like a function argument definition in that a matching thrown exception is assigned to s. Also, if an exception does match this handler, the program executes the code within the braces.
If a program completes executing statements in a try block without any exceptions being thrown, it skips the catch block or blocks after the try block and goes to the first statement following the handlers. So when the sample run of the program in Listing 15.9 processes the values 3 and 6, program execution goes directly to the output statement and reports the result.