Online Book Reader

Home Category

Professional C__ - Marc Gregoire [163]

By Root 1565 0
listed in its throw list, C++ calls a special function unexpected(). The built-in implementation of unexpected()calls terminate(). However, just as you can set your own terminate_handler, you can set your own unexpected_handler. Unlike in the terminate_handler, you can actually do something other than just terminate the program in the unexpected_handler. Your version of the function must either throw a new exception or terminate the program — it can’t just exit the function normally. If it throws a new exception, that exception will be substituted for the unexpected exception as if the new one had been thrown originally. If this substituted exception is also not listed in the throw list, the program will do one of two things. If the throw list for the function specifies bad_exception, then bad_exception will be thrown. Otherwise, the program will terminate. Custom implementations of unexpected() are normally used to convert unexpected exceptions into expected exceptions. For example, you could write a version of unexpected() like this:

void myUnexpected()

{

cerr << "Unexpected exception!" << endl;

throw runtime_error("");

}

Code snippet from ReadIntegerFile\UnexpectedExceptions.cpp

This code converts an unexpected exception to a runtime_error exception, which the function readIntegerFile() has in its throw list.

You could set this unexpected exception handler in main() with the set_unexpected() function. Like set_terminate(), set_unexpected() returns the current handler. The unexpected() function applies program-wide, not just to this function, so you should reset the handler when you are done with the code that needed your special handler:

int main()

{

vector myInts;

const string fileName = "IntegerFile.txt";

unexpected_handler old_handler = set_unexpected(myUnexpected);

try {

readIntegerFile(fileName, myInts);

} catch (const invalid_argument& e) {

cerr << "Unable to open file " << fileName << endl;

return 1;

} catch (const runtime_error& e) {

cerr << "Error reading file " << fileName << endl;

return 1;

} catch (int x) {

cerr << "Caught int" << endl;

}

set_unexpected(old_handler);

// Remainder of function omitted

}

Code snippet from ReadIntegerFile\UnexpectedExceptions.cpp

Now main() handles any exception thrown from readIntegerFile() by converting it to a runtime_error. However, as with set_terminate(), we recommend using this capability judiciously.

unexpected(), set_unexpected(), and bad_exception are all declared in the header file.

Changing the Throw List in Overridden Methods

When you override a virtual method in a subclass, you can change the throw list as long as you make it more restrictive than the throw list in the superclass. The following changes qualify as more restrictive:

Removing exceptions from the list

Adding subclasses of exceptions that appear in the superclass throw list

Making it a noexcept method

The following changes do not qualify as more restrictive:

Adding exceptions to the list that are not subclasses of exceptions in the superclass throw list

Removing the throw list entirely

If you change throw lists when you override methods, remember that any code that called the superclass version of the method must be able to call the subclass version. Thus, you can’t add exceptions.

For example, suppose that you have the following superclass:

class Base

{

public:

virtual void func() throw(exception) { cout << "Base!\n"; }

};

Code snippet from ThrowListsVirtualMethods\CorrectOne.cpp

You could write a subclass that overrides func() and specifies that it doesn’t throw any exceptions:

class Derived : public Base

{

public:

virtual void func() noexcept { cout << "Derived!\n"; }

};

Code snippet from ThrowListsVirtualMethods\CorrectOne.cpp

You could also override func() such that it throws a runtime_error as well as an exception, because runtime_error is a subclass of exception.

class Derived : public Base

{

public:

virtual void func() throw(exception, runtime_error)

{ cout << "Derived!\n"; }

};

Code snippet from

Return Main Page Previous Page Next Page

®Online Book Reader