18.1.3. Function try Blocks and Constructors

In general, exceptions can occur at any point in the program’s execution. In particular, an exception might occur while processing a constructor initializer. Constructor initializers execute before the constructor body is entered. A catch inside the constructor body can’t handle an exception thrown by a constructor initializer because a try block inside the constructor body would not yet be in effect when the exception is thrown.


Exercises Section 18.1.2

Exercise 18.4: Looking ahead to the inheritance hierarchy in Figure 18.1 (p. 783), explain what’s wrong with the following try block. Correct it.

try {
    // use of the C++ standard library
} catch(exception) {
    // ...
} catch(const runtime_error &re) {
    // ...
} catch(overflow_error eobj) { /* ... */ }

Image

Figure 18.1. Standard exception Class Hierarchy

Exercise 18.5: Modify the following main function to catch any of the exception types shown in Figure 18.1 (p. 783):

int main() {
    // use of the C++ standard library
}

The handlers should print the error message associated with the exception before calling abort (defined in the header cstdlib) to terminate main.

Exercise 18.6: Given the following exception types and catch clauses, write a throw expression that creates an exception object that can be caught by each catch clause:

(a) class exceptionType { };

catch(exceptionType *pet) { }

(b) catch(...) { }

(c) typedef int EXCPTYPE;

catch(EXCPTYPE) { }


To handle an exception from a constructor initializer, we must write the constructor as a function try block. A function try block lets us associate a group of catch clauses with the initialization phase of a constructor (or the destruction phase of a destructor) as well as with the constructor’s (or destructor’s) function body. As an example, we might wrap the Blob constructors (§ 16.1.2, p. 662) in a function try block:

template <typename T>
Blob<T>::Blob(std::initializer_list<T> il) try :
              data(std::make_shared<std::vector<T>>(il)) {
         /* empty body */
} catch(const std::bad_alloc &e) { handle_out_of_memory(e); }

Notice that the keyword try appears before the colon that begins the constructor initializer list and before the curly brace that forms the (in this case empty) constructor function body. The catch associated with this try can be used to handle exceptions thrown either from within the member initialization list or from within the constructor body.

It is worth noting that an exception can happen while initializing the constructor’s parameters. Such exceptions are not part of the function try block. The function try block handles only exceptions that occur once the constructor begins executing. As with any other function call, if an exception occurs during parameter initialization, that exception is part of the calling expression and is handled in the caller’s context.


Image Note

The only way for a constructor to handle an exception from a constructor initializer is to write the constructor as a function try block.



Exercises Section 18.1.3

Exercise 18.7: Define your Blob and BlobPtr classes from Chapter 16 to use function try blocks for their constructors.


..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.14.144.108