home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.lang.c++
- Path: sparky!uunet!centerline!matt
- From: matt@centerline.com (Matt Landau)
- Subject: Re: Return value for the constructors.
- Message-ID: <matt.714407976@centerline.com>
- Sender: news@centerline.com
- Nntp-Posting-Host: rapier
- Organization: CenterLine Software, Inc.
- References: <1992Aug19.231926.28218@sunb10.cs.uiuc.edu> <2273@devnull.mpd.tandem.com> <matt.714318343@centerline.com> <2284@devnull.mpd.tandem.com>
- Distribution: usa
- Date: Fri, 21 Aug 1992 14:39:36 GMT
- Lines: 72
-
- In <2284@devnull.mpd.tandem.com> rgp@mpd.tandem.com (Ramon Pantin) writes:
- >So, to get an error code out of a constructor we should (note that I
- >DON'T agree with all this!):
- >
- >- Forbid the creation of automatic variables and arrays, i.e. make
- > the constructors non-public.
- >
- >- Do the new/constructor thing.
- >
- >- Have some public static member function that creates objects.
- >
- >Sounds pretty convuluted, don't you think?
- >No wonder nobody seems to write simple code anymore!
-
- Well, as the person who pointed out how one can make constructors private,
- let me hasten to add that I don't actually recommend this approach; I was
- just pointing out that it *is* possible.
-
- In addition to the "forbid automatic objects and overload operator new"
- approach, there are two other things one can do about constructor failures
- in a C++ environment that lacks exceptions:
-
- (1) Have an "isValid" bit in every object, which the constructor sets
- or clears before returning. Application code is then responsible
- for testing "obj.isValid" before using any object. I know of a
- couple of different class libraries that have taken this approach.
- The penalty for not testing the isValid bit is using a potentially
- uninitialized or invalid object.
-
- (2) Try very hard to write constructors that cannot fail, and move any
- failure-prone initialization (like dynamic allocation) to some
- secondary initialization routine. Application code then becomes
- responsible for calling "obj.Init()" before using any object. The
- penalty for omitting the call is using a potentially uninitialized
- or invalid object.
-
- You can sort of get around this problem if you can make sure the
- Init member function requires no arguments (so it can be called
- from anywhere within the class's own implementation), keep an
- isInitialized bit in the object, have EVERY member function of
- the object test isInitialized and call Init if needed, and forbid
- the use of public data members, escshewing them in favor of inline
- member functions of the form:
-
- inline int X::Count(void) const
- {
- if (!isInitialized) Init();
- return _count;
- }
-
- Of course, this approach is also a big kludge, inconvenient to
- maintain, and subject to code size explosion if you have a large
- number of short member functions.
-
- The fact that both of these approaches leave you with the potential for
- using an incompletely initialized object (the very thing constructors in
- C++ were supposed to prevent!) points to a basic shortcoming in most of
- the current implementations of the language.
-
- The underlying point is that without a decent exception system, there
- is **NO** good way to deal with the problem of constructor failures.
- There are several different not-so-good ways to choose from; which one
- you choose depends on the nature of the system you're writing.
-
- Even *with* a decent exception system, the problem doesn't just go away.
- Exceptions provide a mechanism and a framework within which one can deal
- with this problem (as well as many other problems). The design skills
- and engineering discipline needed to use exceptions both correctly and
- robustly are still not to be underestimated.
- --
- Matt Landau Waiting for a flash of enlightenment
- matt@centerline.com in all this blood and thunder
-