views:

242

answers:

4

Is it possible to handle exceptions in these scenarios:

  1. thrown from constructor before entering main()
  2. thrown from destructor after leaving main()
A: 

It might be possible to set an exception handler before construction / destruction of the objects in question, that one should be able to handle those exceptions.

For constructors, there's some weird new syntax that allows exceptions to be caught within the constructor. Not sure how that works, and it's not commonly implemented in many compilers.

For destructors, you have to wrap the content of the destructor in a try { code(); } catch(...) {} block. Which may not always be the desired behavior, depending on what you want to achieve in that destructor.

tobing
"New" as in over 15 years old? :P It *is* commonly implemented and is part of the C++ standard.
Roger Pate
+15  A: 
  1. You can wrap up your constructor withing a try-catch inside of it.
  2. No, you should never allow exception throwing in a destructor.

The funny less-known feature of how to embed try-catch in a constructor:

object::object( int param )
try
  : optional( initialization )
{
   // ...
}
catch(...)
{
   // ...
}

Yes, this is valid C++. The added benefit here is the fact that the try will catch exceptions thrown by the constructors of the data members of the class, even if they're not mentioned in the ctor initializer or there is no ctor initializer:

struct Throws {
  int answer;
  Throws() : answer(((throw std::runtime_error("whoosh!")), 42)) {}
};

struct Contains {
  Throws baseball;
  Contains() try {} catch (std::exception& e) { std::cerr << e.what() << '\n'; }
};
Kornel Kisielewicz
2:30 am and I already learned something today!
Potatoswatter
+1 Did not know that was valid C++. Learnt something today.
Tarydon
I was surprised when I've learned it too :). It's one of those less known features...
Kornel Kisielewicz
Ah, forgot about optional initializators passing. Now it's fully esoteric.
Kornel Kisielewicz
Function try-blocks also work for almost any function, including main (where you should practically always have one).
Roger Pate
But only in constructors they have the real benefit of wrapping the initialization of objects.
Kornel Kisielewicz
Note that the exception will always be rethrown at end of the constructor (to prevent there being an object with uninitialised members).
James Hopkin
You did not use that "less known feature" in the sample. I tried the sample in VC2008, but the exception propagated to the main.
Jagannath
Jagannath: As James pointed out, you cannot silence exceptions from data members' ctors, you *must* propagate them. The output will still be written to stderr, to show that it was caught, however.
Roger Pate
Point 2 could use a tweak: "No, you should never allow exceptions to escape from a destructor." A function, called from a dtor, which throws is fine, the dtor just must make sure to handle it.
Roger Pate
I wonder if a call to exit() would also be OK in the constructor-level try block? In any case, there doesn't seem to be any way to recover, since there is no place to continue from as the program hasn't even started to run. But one probably doesn't want to recover from fatal errors in global construction anyway...
UncleBens
+4  A: 

Yes: don't use dangerous global objects!

Potatoswatter
This is the best answer (after you add "or dangerous singletons"), but I'm out of votes for the next 14 hours!
Roger Pate
+1: in name of Roger -- however, I'd like to point out that there are situations that this is impossible, especially if using some wierd API that makes the decision for you.
Kornel Kisielewicz
I'm just happy not to get downvoted - LOL
Potatoswatter
A: 

Short answer: no.

Any global object that throws an exception in its constructor will cause an unhandled exception (that is, terminate be called).

Any class that throws an exception in its destructor is a broken class.

Using the singleton pattern rather than globals will give you more options.

James Hopkin
I find the opposite: singletons reduce options. Putting application-level objects as local variables in main works beautifully though.
Roger Pate
@Roger I don't think we disagree - I only said singletons give you more options than globals.
James Hopkin
No, I think singletons reduce options compared to global objects, as at least with globals you can put them all in one TU to control initialization order, and other such things.
Roger Pate
Oh, we do disagree then ;-). Singletons are only created if and when needed, and in the rare case of one singleton depending on another, that works automatically, rather than the object instances having to be carefully ordered. Singletons can also be kept private to a particular area of code, rather than needing to be dumped in main.cpp. And wrt to the original question, a variation on the singleton pattern would allow you to handle a singleton not constructing properly (perhaps grey out the UI and display an error, rather than crashing).
James Hopkin