8

I have a question about how to catch the exception in the initialization list.

For example, we have a class Foo derived from Bar

class Foo {

public:
Foo(int i) {throw 0; }

}

class Bar : public Foo{

public:

Bar() : Foo(1) {}

}
skydoor
  • 25,218
  • 52
  • 147
  • 201

4 Answers4

11

I think the syntax is like this (even though it's better to catch such things in the caller. And what are you going to do once you caught it?)

Bar::Bar()
try
  : Foo(1)
{
}
catch( const SomeException &e )
{
}
  • 5
    Whoa, that is some weird-looking code. – Michael Myers Mar 14 '10 at 02:53
  • 4
    Note that this can't be used to ignore the exception. If the `catch` block doesn't throw an exception on it's own, the original exception is automatically rethrown (See the linked GOTW for details). – sth Mar 14 '10 at 03:03
  • @sth: sure it can, just `return`. – Potatoswatter Mar 14 '10 at 03:27
  • 4
    @Potatoswatter, no it can't. You can't even `return;` in the body of such a `catch` block for a ctor-initializer, as far as i know (as opposed to the catch block of other function try blocks). – Johannes Schaub - litb Mar 14 '10 at 03:33
  • @Johannes: hey, you're right, §15.3/15. Furthermore you can't attempt to perform initialization: "Referring to any non-static member or base class of an object in the handler for a function-try-block of a constructor or destructor for that object results in undefined behavior." That kinda sucks! – Potatoswatter Mar 14 '10 at 03:58
  • @Potatoswatter: It doesn't suck, there is just no object you could refer to at that point. – Georg Fritzsche Mar 14 '10 at 04:41
  • @gf: that sounds a bit strong. You could have nothrow guarantees on all but the last-initialized base/nonstatic member, and be certain they're valid. Granted that a more accommodating language spec wouldn't be very easy, or particularly useful. – Potatoswatter Mar 14 '10 at 04:50
  • @Potatos, so when the last-initialized member constructor throws, what are you supposed to do in your catch? You can't "repair" it, since the object in question would have done it itself if it could (it certainly has more knowledge about itself). You can just resignate and let the exception escape. So what would it buy you if you could access the other members? Notice that the destructors of the other members are called automatically if a later initialized member throws. So everything is cleaned nicely. – Johannes Schaub - litb Mar 14 '10 at 05:16
  • @Johannes: We can suppose that the throwing object may be inessential. Alternately, knowing the partially-constructed state could be useful for debugging output. I think it's probably easier to implement running the catch block after previously-initialized members are destroyed rather than destroy them after the rethrow, though. I'm not saying this is a big deal, but I can imagine frustration resulting. – Potatoswatter Mar 14 '10 at 06:03
6

C++ has a mechanism for doing so, but it is rarely used. It is the function try block:

Bar::Bar()
try
  : Foo(1)
{
}
catch( Something )
{
}

See this classic gotw, which outlines why it should only be used to translate exceptions (e.g., exception type FooException becomes BarException).

Todd Gardner
  • 13,313
  • 39
  • 51
1

I believe this should be caught by the procedure creating the object.

Spencer Ruport
  • 34,865
  • 12
  • 85
  • 147
0

Consider replacing the troublesome instance with a boost::optional. Then you can defer its initialization into the body of the constructor.

Potatoswatter
  • 134,909
  • 25
  • 265
  • 421