Re: Throwing exception in constructor
 
* kanze:
Alf P. Steinbach wrote:
* sunil:
 According to my research so far, its OK to
 throw an exception in a constructor, only thing is that
 destructor for that class wont be called,
Almost right.  It's not just OK to throw an exception to
signal a construction failure.  In not-extremely-badly
designed code it's mandatory, to ensure you only ever deal
with fully initialized objects, and no half-way constructed
objects (doing the opposite is one way of streching a 2 to 3
hour programming job into 2 or 3 weeks...).
That's generally the rule.  But there are exceptions, and I
wouldn't consider the iostream hierarchy poorly designed because
ifstream doesn't throw if it cannot open the file.
Right  --  the effects of the poor design shows up in other ways... ;-)
Anytime an
object can become invalid during its lifetime (and so later
tests of validity or success are necessary anyway), the argument
based on the absense of invalid objects looses its power.
Just a little.  Mostly the argument is against an additional nullstate 
(zombie state) /mixed in with other state/, which must be checked 
everywhere, leading to complexity (a.k.a. spaghetti) and bugs.  As an 
example, and this is a special case of a well-known state pattern I 
forget the name of, access of an object representing an open file can be 
restricted to a special kind of smart-pointer so that the "real" object 
doesn't need to deal with the nullstate, except notifying the containing 
smart pointer of its further non-existence, and so that the containing 
smart pointer only deals with (throwing exceptions on operations on) 
nullstate: clean code in both classes, and reusable generic nullstate.
Why isn't it ordinarily done that way?
Well, why am I currently fighting with triple-phase initialization and 
other monstrosities?  I think there's a very strong tendency to design 
and code /locally/ for what the slightly less than average programmer in 
the firm/shop/project can be expected to understand and maintain.  Then 
this seemingly bright idea yields unmaintainable global spaghetti, which 
in turn yields local spaghetti, 99.7% contrary to what one aimed for.
(Depending on the case, there may be other arguments for
exceptions in such cases.  But it's not the cut and dried case
it would be otherwise.)
There are also probably a few rare cases (although I can't think
of any off hand) where it is justified to use a factory
function, which either separates initialization from
construction, or tests the success of the constructor, and in
case of failure, deletes the object and returns a null pointer.
Ah, you're thinking of deserialization... ;-)
At least, I've been thinking about it lately.
There is a conflict there between the initialization order imposed by 
C++ and the order very strongly suggested by the serialized data.  One 
solution is buffering, another and probably both more practical and 
efficient solution is to cast the data member declaration order in stone 
for serializable objects, and a third is to not regard the serialized 
data as a stream, but as random access.  Whatever solution one adopts 
(and mostly it seems serialization frameworks, including the one in 
Boost, choose none of these reasonable options and instead go for ugly 
two-phase initialization) there is some trade-off: that's engineering.
Cheers,
- Alf
-- 
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]