Exceptions And Constructors

One problem I find when using exceptions in C++ code is when a constructor throws an exception. If I write something like this ...

try {
Something someThing(params);
} catch(Some_Exception e) {
// Handle this properly
}
... someThing is no longer in scope by this point, which means that I have to write code like this:

try {
Something someThing;
someThing.Do_Something();
} catch(SomeException? e) {
// Now, who threw the exception?
// The constructor or the method call?
}
And that I don't like. In this case, I tend to use TwoPhaseConstruction?, even though I know it's evil for a host of other reasons.

-- RogerLipscombe

I can't figure out at all what you are saying here, as someThing isn't in scope in your second example either (perhaps this is the indictment - that even a trivial example requires too much thought). However, it looks to me as though you are trying to do too much in one place. It looks to me as though one of these might meet your needs:

try {
Something someThing(params);
someThing.do () ;
} catch(Something_Constructor_Exception e) {
// Handle this properly
// someThing is not in scope
} catch(Something_Do_Exception e ) {
// Handle this differently
// someThing is not in scope
}
or maybe

void Do ( Something someThing ) // does not throw SomeException?
{
try {
someThing.do () ;
} catch ( SomeException? e ) {
// Handle this properly
// someThing is in scope
}
}

try { Something someThing(params) ; Do( someThing ) ; } catch ( SomeException? e ) { // Handle this - it must be an exception in the constructor // someThing not in scope }
-- DanilSuits


Upon further thought (the therapeutic properties of hot water in action) it seems to me that all code which handles exceptions ought to have the following form:

DoSomething? ( args )
{
Context crntContext(args); // Can't throw

try { actuallyDoIt( crntContext ) ; } catch ( Exception1 e ) { HandleException1( e, crntContext ) ; } ... catch ( ExceptionN e ) { HandleExceptionN( e, crntContext ) ; } }
I'm inclined to think that failure to permit this form is a CodeSmell. -- DanilSuits


I think that some of the confusion and frustration can be cleared up by defining when a constructor should throw an exception. To me, a constructor must throw an exception when instantiation of the object is simply not possible. This is backed up by the semantics of a constructor exception: when the constructor throws, it's as if the object never existed in the first place.

So the only way to legally write the first example is this:

try {
Something someThing;
        try {
        someThing.Do_Something();
        } catch(SomeException? e) {
         // someThing decided it was impossible to Do_Something(), so it threw.
        } 
} catch(SomeException? e) {
// someThing doesn't exist, because the constructor found it impossible to instantiate it.
} 

-- TimLesher

(Fixed code so it actually will work; DeleteWhenCooked.)


CategoryException


EditText of this page (last edited October 17, 2006) or FindPage with title or text search