Solution

I l @ ve RuBoard

graphics/bulb.gif

Function try blocks were added to C++ to slightly enlarge the scope of exceptions that a function can catch. This Item covers

  • What object construction and construction failure mean in C++; and

  • That function try blocks are useful to translate (not suppress) an exception thrown from a base or member subobject constructor ”and that's pretty much it.

For convenience, throughout this Item, member means "nonstatic class data member" unless otherwise noted.

Function Try Blocks

1. Consider the following class:

  // Example 17-1   //   class C : private A   {   B b_;   };  

In the C constructor, how can you catch an exception thrown from the constructor of a base subobject (such as A ) or a member object (such as b_ )?

That's what function try blocks are for:

 // Example 17-1(a): Constructor function try block // C::C() try   : A ( /*...*/ )   // optional initialization list   , b_( /*...*/ ) { } catch( ... ) {   // We get here if either A::A() or B::B() throws.   // If A::A() succeeds and then B::B() throws, the   // language guarantees that A::~A() will be called   // to destroy the already-created A base subobject   // before control reaches this catch block. } 

The more interesting question, though, is: Why would you want to do this? That question brings us to the first of two key points in this Item.

Object Lifetimes and What a Constructor Exception Means

In a moment, we'll consider the question of whether the above C constructor can, or should, absorb an A or B constructor exception and emit no exception at all. But before we can answer that question correctly, we need to make sure we fully understand object lifetimes [1] and what it means for a constructor to throw an exception.

[1] For simplicity, I'm speaking only of the lifetime of an object of class type that has a constructor.

2. Consider the following code:

  // Example 17-2   //   {   Parrot p;   }  

When does the object's lifetime begin? When does it end? Outside the object's lifetime, what is the status of the object? Finally, what would it mean if the constructor threw an exception?

Let's take the questions one at a time:

Q:

When does an object's lifetime begin?

A:

When its constructor completes successfully and returns normally. That is, when control reaches the end of the constructor body or completes an earlier return statement.

Q:

When does an object's lifetime end?

A:

When its destructor begins. That is, when control reaches the beginning of the destructor body.

Q:

What is the state of the object after its lifetime has ended?

A:

As a well-known software guru once put it while speaking about a similar code fragment and anthropomorphically referring to the local object as a "he":

  // Example 17-3   //   {   Parrot& perch = Parrot();   // ...   }   // <-- the soliloquy takes place here  

He's not pining! He's passed on! This Parrot is no more! He has ceased to be! He's expired and gone to meet his maker! He's a stiff! Bereft of life, he rests in peace ! If you hadn't nailed him to the perch he'd be pushing up the daisies [even earlier, before the end of the block]! His metabolic processes are now history! He's off the twig! He's kicked the bucket, he's shuffled off his mortal coil, run down the curtain and joined the bleedin' choir invisible! This is an ex- Parrot !

”Dr. M. Python, B.Math, MA.Sc., Ph.D. (CompSci) [2]

[2] With apologies to Monty Python.

Kidding aside, the important point here is that the state of the object before its lifetime begins is exactly the same as after its lifetime ends: There is no object, period. This observation brings us to the next key question:

Q:

What does emitting an exception from a constructor mean?

A:

It means that construction has failed, the object never existed, its lifetime never began . Indeed, the only way to report the failure of construction ”namely, the inability to correctly build a functioning object of the given type ”is to throw an exception. (Yes, there is a now-obsolete programming convention that said: "If you get into trouble, just set a status flag to 'bad' and let the caller check it via an IsOK() function." I'll comment on that presently.)

Incidentally, this is why a destructor will never be called if the constructor didn't succeed ”there's nothing to destroy. It cannot die, for it never lived. Note that this makes the phrase "an object whose constructor threw an exception" really an oxymoron. Such a thing is even less than an ex-object. It never lived, never made it to objecthood. It is a non-object.

We might summarize the C++ constructor model as follows :

Either:

  1. The constructor returns normally by reaching its end or a return statement, and the object exists, or

  2. The constructor exits by emitting an exception, and the object not only does not now exist, but it never existed as an object.

There are no other possibilities. Armed with this information, we can now better tackle the next Item's question: What about absorbing exceptions?

I l @ ve RuBoard


More Exceptional C++
More Exceptional C++: 40 New Engineering Puzzles, Programming Problems, and Solutions
ISBN: 020170434X
EAN: 2147483647
Year: 2001
Pages: 118
Authors: Herb Sutter

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