Topic: Calling member functions in the constructor/destructor


Author: v.Abazarov@attAbi.com ("Victor Bazarov")
Date: Mon, 6 Jan 2003 03:51:15 +0000 (UTC)
Raw View
"Allan W" <allan_w@my-dejanews.com> wrote...
> musiphil@bawi.org (KIM Seungbeom) wrote
> > Allan W wrote:
> > >
> > > The code in the constructor helps finish turning the raw memory into
> > > the object. Just as it is allowed to act on the nonstatic data
members,
> > > it's also able to call nonstatic functions which act on that member
> > > data. Similarly, the destructor helps finish cleaning up the object
> > > as it's turning into raw memory.
> > >
> > > The standard doesn't prevent calling nonstatic member functions.
> >
> > But then, why does 3.8/5 says that "the program has undefined behavior
> > if the pointer is used to [...] call a non-static member function of
> > the object [outside its lifetime]?" I wanted to know how the apparent
> > contradiction mentioned in the earlier posting of mine was solved..
>
> Not sure there's a good answer to that.
>
> Suppose a mother goes into labor at 11:45 PM on December 31. At 11:59 PM,
> the baby begins to emerge from the birth canal. At 12:01 AM, the baby
> has finished emerging. When was the baby born?

The baby is born when it clears the birth canal.  But it has no
bearing on the lifetime of the organism.  Some will consider that
the lifetime starts when the baby draws its first breath.  Others
will say that it's when the ambilical chord is cut.  Yet others say
that life starts at conception.  If you need the precise moment,
you have to define it and then stick to the definition.

> In some sense, a Foo isn't a Foo until Foo's constructor has completed.
> But in some other sense, a Foo is a Foo as soon as Foo's constructor
> has started.

I believe that in the current edition the Standard is quite
unambiguous about that.  See 3.8/1.  It may require changing, but
as it stands now, the object doesn't exist yet until the
constructor finished.

> AFAIK, calls made from the body of a constructor are (generally)
> considered to have executed during the object's lifetime, even though
> (as others have said) the state might not yet be 100% stable.

Considered (and implemented), yes.  If that's the agreement, the
Standard needs to be changed.  It prohibits calling non-static member
functions from a constructor body if you follow its letter.  If that
is settled, I think that the first "bullet" in the 3.8/5 that now
reads

 "- the pointer is used to access a non-static data member or call
    a non-static member function of the object,
    or"

should read

 "- the pointer is used to access a non-static data member or call
    a non-static member function of the object (except in the body
    of a constructor or destructor), or"

(or something to that extent, I am not very good at making up
definitions)

Victor
--
Please remove capital A's from my address when replying by mail

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: allan_w@my-dejanews.com (Allan W)
Date: Sun, 5 Jan 2003 10:07:41 +0000 (UTC)
Raw View
musiphil@bawi.org (KIM Seungbeom) wrote
> Allan W wrote:
> >
> > The code in the constructor helps finish turning the raw memory into
> > the object. Just as it is allowed to act on the nonstatic data members,
> > it's also able to call nonstatic functions which act on that member
> > data. Similarly, the destructor helps finish cleaning up the object
> > as it's turning into raw memory.
> >
> > The standard doesn't prevent calling nonstatic member functions.
>
> But then, why does 3.8/5 says that "the program has undefined behavior
> if the pointer is used to [...] call a non-static member function of
> the object [outside its lifetime]?" I wanted to know how the apparent
> contradiction mentioned in the earlier posting of mine was solved..

Not sure there's a good answer to that.

Suppose a mother goes into labor at 11:45 PM on December 31. At 11:59 PM,
the baby begins to emerge from the birth canal. At 12:01 AM, the baby
has finished emerging. When was the baby born?

In some sense, a Foo isn't a Foo until Foo's constructor has completed.
But in some other sense, a Foo is a Foo as soon as Foo's constructor
has started.

AFAIK, calls made from the body of a constructor are (generally)
considered to have executed during the object's lifetime, even though
(as others have said) the state might not yet be 100% stable.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: musiphil@bawi.org (KIM Seungbeom)
Date: Thu, 2 Jan 2003 04:07:57 +0000 (UTC)
Raw View
Allan W wrote:
>
> The code in the constructor helps finish turning the raw memory into
> the object. Just as it is allowed to act on the nonstatic data members,
> it's also able to call nonstatic functions which act on that member
> data. Similarly, the destructor helps finish cleaning up the object
> as it's turning into raw memory.
>
> The standard doesn't prevent calling nonstatic member functions.

But then, why does 3.8/5 says that "the program has undefined behavior
if the pointer is used to [...] call a non-static member function of
the object [outside its lifetime]?" I wanted to know how the apparent
contradiction mentioned in the earlier posting of mine was solved..

--
KIM Seungbeom <musiphil@bawi.org>

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: allan_w@my-dejanews.com (Allan W)
Date: Thu, 26 Dec 2002 16:40:27 +0000 (UTC)
Raw View
musiphil@bawi.org (KIM Seungbeom) wrote
> In the constructor of an object, the lifetime of the object has not
> been started. In the destructor, the lifetime has ended.
> In these functions, is it legal to call non-static member functions
> on that object?

The code in the constructor helps finish turning the raw memory into
the object. Just as it is allowed to act on the nonstatic data members,
it's also able to call nonstatic functions which act on that member
data. Similarly, the destructor helps finish cleaning up the object
as it's turning into raw memory.

The standard doesn't prevent calling nonstatic member functions. You
may be thinking of the rules about virtual function calls? Recall
that Base is constructed before Derived. At the point that Base's
constructor is executing, Derived's constructor has not yet started...
and therefor RTTI, virtual calls, and everything else indicate that
the object is a Base, not a Derived (even if Base is an abstract
type). That's why you can't call any virtual functions that aren't
defined in Base, and if you call functions overridden in Derived,
the Base version is called instead.

    struct Base {
        Base() { what(); }
        virtual ~Base() { what(); }
        virtual void what() = 0;
    };
    void Base::what() { std::cout << "I am a BASE\n"; }

    struct Der : public Base {
        Der() { what(); }
        ~Der() { what(); }
        void what();
    };
    void Der::what() { std::cout << "I am a DER!\n"; }

    int main() {
        std::cout << "Hello:\n";
        Base *b = new Der;

        std::cout << "Identity: ";
        b->what();

        delete b;
        std::cout << "Goodbye:\n";
    }

Output should be:
    Hello:
    I am a BASE
    I am a DER!
    Identity: I am a DER!
    Goodbye:
    I am a DER!
    I am a BASE

Function what() is virtual, so b->what() calls Der::what. But when the
same call is made from Base's constructor or destructor, it calls
Base::what -- because at that point the object is a Base, not a Der.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: philippe_mori@hotmail.com (Philippe Mori)
Date: Thu, 26 Dec 2002 18:45:13 +0000 (UTC)
Raw View
You can call any member function in your constructor provide that you are
sure that:

1) You do not call a virtual function either directly or indirectly or that
it is OK to call the function without virtuallity. One of the worst case
would be to call a pure virtual function indirectly...

2) Data that is used by the function is initialized properly when the
function is called.

3) With Visual C++, you cannot call virtually a function if the class is
declared without v-table (a common optimisation for ATL base classes).

4) You ensure that your code properly handle error conditions... For
example, if an exception occurs in one of those function, it may be a bit
harder to ensure that the code is exception-safe. Also some maintenance
changes in those function may have an undesirable effect on construction (or
destruction) but be OK in other cases...



---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: francis.glassborow@ntlworld.com (Francis Glassborow)
Date: Thu, 26 Dec 2002 19:30:46 +0000 (UTC)
Raw View
In article <3e0691a4@news.toast.net>, Scott Mayo <scottm@toast.net>
writes
>If anything can throw inside the constructor, arrange to catch inside
>the constructor. Otherwise, badness may occur.

Did you mean that? or did you type dtor where you meant dtor?

--
ACCU Spring Conference 2003 April 2-5
The Conference you cannot afford to miss
Check the details: http://www.accuconference.co.uk/
Francis Glassborow      ACCU

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: musiphil@bawi.org (KIM Seungbeom)
Date: Sun, 22 Dec 2002 21:53:58 +0000 (UTC)
Raw View
In the constructor of an object, the lifetime of the object has not
been started. In the destructor, the lifetime has ended.
In these functions, is it legal to call non-static member functions
on that object?

It seems that 3.8/5 forbids it while 12.7/3 allows it.
I found that this contradiction was discussed in comp.std.c++ at
http://groups.google.com/groups?selm=5ijfpa%245ru%40mulga.cs.mu.OZ.AU
but it was in 1997, before the standardization. I read in that
posting that it was a bug, but I still see the same contradiction
in the current standard.

--
KIM Seungbeom <musiphil@bawi.org>

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: scottm@toast.net ("Scott Mayo")
Date: Thu, 26 Dec 2002 08:29:48 +0000 (UTC)
Raw View
"KIM Seungbeom" <musiphil@bawi.org> wrote in message
news:3E05E538.5BDBB53B@bawi.org...

> In the constructor of an object, the lifetime of the object has not
> been started. In the destructor, the lifetime has ended.
> In these functions, is it legal to call non-static member functions
> on that object?

Practically speaking, in the destructor, the object's lifetime has not
yet ended. You can call anything at that point except the destructor
itself.

In the constructor, the object is in an unknown state at the start
of the function, but if you call member functions that don't rely
on any given state, that's not a problem. It comes down to common
sense: don't call any function that requires the object be in a state
if you haven't yet put the object into that state. You simply have to
be careful how you initialize and use the object.

If anything can throw inside the constructor, arrange to catch inside
the constructor. Otherwise, badness may occur.



---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]