[comp.lang.c++] 'this' in member initialization

chatty%FRLRI61.BITNET@CUNYVM.CUNY.EDU (02/08/91)

// the following program is accepted by both g++ and cfront 2.0.
// It leads to the suprising thing that a virtual method of class B is
// called before the body of the constructor is entered.

// I think ARM, p47, s5.1,  forbids the use of 'this' in member
// initialization.

// any comments?

extern "C" void printf (const char*, ...);

class A {
public:
 A () {}
 virtual void foo () {printf ("A::foo\n");}
};

class Z {
public:
 Z (A* a) {a->foo ();}
};

class B : public A {
public:
 Z z;
 B () : A (), z (this) {printf ("B::B\n");} // legal?!
 void foo () {printf ("B::foo\n");}
};

main ()
{
 B b;
}

// % a.out
// B::foo
// B::B



Stephane Chatty         chatty@lri.lri.fr, chatty@frlri61.bitnet

jak@cs.brown.edu (Jak Kirman) (02/09/91)

In article <9102080900.AA19725@lri.lri.fr> chatty%FRLRI61.BITNET@CUNYVM.CUNY.EDU writes:
   // the following program is accepted by both g++ and cfront 2.0.
   // It leads to the suprising thing that a virtual method of class B is
   // called before the body of the constructor is entered.

   // I think ARM, p47, s5.1,  forbids the use of 'this' in member
   // initialization.

   extern "C" void printf (const char*, ...);

   class A {
   public:
    A () {}
    virtual void foo () {printf ("A::foo\n");}
   };

   class Z {
   public:
    Z (A* a) {a->foo ();}
   };

   class B : public A {
   public:
    Z z;
    B () : A (), z (this) {printf ("B::B\n");} // legal?!
    void foo () {printf ("B::foo\n");}
   };

   main ()
   {
    B b;
   }

   // % a.out
   // B::foo
   // B::B

I think the wording is poor in the section of the ARM you refer to.  I
think the intent is to say that "this" cannot be used except inside a
member function OR a member initialization list.

It is perfectly legal to call a B function from the member
initialization list of B (directly or indirectly); you can initialize an
integer member of B with a call to a function of B.  If that function
accesses members which are declared later, you lose.

[  
[  As an aside, this is a common and painful mistake:
[  
[  class Base {
[  public:
[    int b;
[    int a;
[    Base (int i) : a (i), b (a) {}  // b initialized to garbage
[  };
[  
[  The members are initialized in the order they are declared: b, then a,
[  not in the order they appear in the member initialization list.


Within the body of a constructor or the member initialization list,
calls to member functions of objects *more derived* cannot be made.  So
B's member initialization list can call B member functions, but A's
member initialization list cannot call B member functions.

                                Jak                            jak@cs.brown.edu
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
I never use a pen. I write with a goose quill dipped in venom.
                                               -- Waldo Lydecker, in `Laura'