FAQ 26.06 What should an object do if one of its member objects could throw an exception during its constructor?

graphics/new_icon.gif

Nothing, but the object and its member objects should be designed to manage their own destruction.

First some background. When the constructor of a member object throws an exception, member objects that have already been constructed are destructed. For example, if an object has member objects x_ and y_, and if x_'s constructor succeeds (doesn't throw) and y_'s constructor throws an exception, then x_'s destructor is invoked. However the object that has member objects x_ and y_ was not fully constructed, so the object's destructor is not called.

The easiest way to make things work correctly is to ensure that the destructor for each member object manages its own destruction and does not rely on the composite's destructor to do anything important (since the composite's destructor is not executed). So x_'s destructor must completely handle the destruction of x_ without relying on any help from the composite's destructor. This is illustrated in the following example.

 #include <iostream> #include <stdexcept> using namespace std; class X { public:   X() throw();  ~X() throw(); }; X::X()  throw() { cout << "X ctor\n"; } X::~X() throw() { cout << "X dtor\n"; } class Y { public:   Y() throw(runtime_error); }; Y::Y() throw(runtime_error) {   cout << "Y ctor throwing\n";   throw runtime_error("thrown from Y ctor"); } class A { public:   A() throw(int);  ~A() throw(); protected:   X x_;   Y y_; }; A::A() throw(int) : x_() , y_()                                               <-- 1 { cout << "A ctor\n"; } A::~A() throw() { cout << "A dtor\n"; } int main() {   try {     A a;     cout << "never gets here\n";   }   catch (exception& e) {     cout << "main caught: " << e.what() << endl;   } } 

(1) The exception is throw from here

The output follows.

 X ctor Y ctor throwing X dtor main caught: thrown from Y ctor 

Because A::~A() was never invoked, it had better not do something important to x_, because those important things won't happen if y_'s constructor throws an exception.

Rule of thumb: Every member object should manage its own destruction.

Note that C++ also allows programmers to put a try block inside a constructor's initialization list. This can be used when the rule-of-thumb is not applied.



C++ FAQs
C Programming FAQs: Frequently Asked Questions
ISBN: 0201845199
EAN: 2147483647
Year: 2005
Pages: 566
Authors: Steve Summit

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net