Jeff Louie wrote:
Hi Jon... I reworded the statement. But it is not only C++ that enforces
this idiom. Even the lowly PHP enforces this idiom. Knowing that the
destructor will only be called on a fully constructed object is integral
to the RAII idiom.
I don't see that it's that integral - it's easy enough to guard against
trying to release resources twice.
IMHO it makes sense that if the _user_ defined
constructor code does not execute to completion then the _user_ defined
destructor code should not execute. This does not stop fully constructed
base objects from calling _their_ destructors. so if [[DefaultObject
alloc]init] succeeds but myObject = [[[DefaultObject alloc]init]myInit]
fails, go ahead and call the destructor of DefaultObject, but _don't_
call the destructor of myObject.
Hmm. "Partially-constructed" objects still need to be garbage
collected, however - so why would they not need to be finalized? What
if the base class constructor succeeds, but the derived class
constructor then fails - would you expect the base class finalizer to
be called, but not the derived class finalizer?
The current behaviour seems consistent to me - you don't need any
special rules about when an object is deemed to be "finalizable". A
"partially-constructed" object is still an object - and may indeed be
used elsewhere, if a constructor (say) adds "this" to a list of
objects, or keeps a static reference somewhere. (Yes, those are both a
bad idea - just listing possibilities :)
In both cases you have to be careful - in the C++ semantics you need to
make absolutely sure that you release any resources acquired during
construction if an exception is thrown. In the CLR semantics you need
to make sure that you don't try to release something that was never
acquired (or which has already been released). I see the latter as
easier though, as there's a single finalizer but there may be many
constructors. Better to only have to be careful in one place :)
Jon