[comp.lang.c++] problem with virtual function

ckl@SIRIUS.RISC.COM (Carl K. Lim) (08/21/90)

Hello.  I have this problem: when I'm calling a virtual function from a parent
class's constructor, it fails to execute the derived class's function.  For
example, in the following program, when B is declared, print() is called from
A's constructor.  But instead of looking up the B::print(), A::print() is
called instead.  Has anybody run into this kind of problem?  Is there a way
to get around it?

	#include <stdio.h>

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


	class B : public A
	{
	public:
	  B() {}
	  void print() { printf("B\n"); }
	};


	int main()
	{
	  B b;
	}

jbuck@galileo.berkeley.edu (Joe Buck) (08/21/90)

In article <9008201757.AA23899@sirius.risc.com>, ckl@SIRIUS.RISC.COM
(Carl K. Lim) writes:
|> Hello.  I have this problem: when I'm calling a virtual function from
a parent
|> class's constructor, it fails to execute the derived class's function.

This is a "feature" and is documented in Ellis and Stroustrup, which is the
base document for the C++ standard.  Why?  Because in the base class
constructor, the derived part of the object hasn't been constructed yet;
it's in an undefined state.


--
Joe Buck
jbuck@galileo.berkeley.edu	 {uunet,ucbvax}!galileo.berkeley.edu!jbuck	

brucec@phoebus.phoebus.labs.tek.com (Bruce Cohen;;50-662;LP=A;) (08/21/90)

In article <9008201757.AA23899@sirius.risc.com> ckl@SIRIUS.RISC.COM (Carl K. Lim) writes:
> 
> 
> Hello.  I have this problem: when I'm calling a virtual function from a parent
> class's constructor, it fails to execute the derived class's function.  For
> example, in the following program, when B is declared, print() is called from
> A's constructor.  But instead of looking up the B::print(), A::print() is
> called instead.  Has anybody run into this kind of problem?  Is there a way
> to get around it?
> 
>     #include <stdio.h>
> 
>     class A
>     {
>     public:
>       A() { print(); }
>       virtual void print() { printf("A\n"); }
>     };
> 
> 
>     class B : public A
>     {
>     public:
>       B() {}
>       void print() { printf("B\n"); }
>     };
> 
> 
>     int main()
>     {
>       B b;
>     }

What you are seeing is the way the language is specified to work:
overloading of a virtual function is ignored when the function is called
from a constructor.  From the bible (Ellis & Stroustrup, "The Annotated C++
Reference Manual") page 294, scectio 12.7:

"Member functions may be called in constructors and destructors. This
 implies that virtual functions may be called (directly or indirectly). The
 function called will be the oned defined in the constructor's (or
 destructor's) own class or its bases, but *not* [italics theirs] any
 functions overriding it in a derived class.  This ensures that
 unconstructed objects will not be accessed during construction and
 destruction."

That insurance is necessary because constructors are called in order from
the base class out towards the derived class.

To get the effect I think you want, put a print(); statement in B's
constructor:

     class B : public A
     {
     public:
       B() { print(); }
       void print() { printf("B\n"); }
     };

If that's not good enough, then you'll have to change your
main to: 

     int main()
     {
       B b;
       b->print();
     }

--
---------------------------------------------------------------------------
NOTE: USE THIS ADDRESS TO REPLY, REPLY-TO IN HEADER MAY BE BROKEN!
Bruce Cohen, Computer Research Lab        email: brucec@tekcrl.labs.tek.com
Tektronix Laboratories, Tektronix, Inc.                phone: (503)627-5241
M/S 50-662, P.O. Box 500, Beaverton, OR  97077

jamshid@walt.cc.utexas.edu (Jamshid Afshar) (08/21/90)

I, too, encountered the problem of not being able to use virtual functions
in a base class constructor.  The only way I know around this is to either
pass the information in the parameter list, or put the stuff which
uses the virt.func. in a init() member function.  I'm glad this came up
because I posted an article to comp.std.c++ about this and have yet to
receive any feedback.   In the article I asked if it were possible to
implement static virtual functions in C++.  I have found the need for
them several times.  Passing stuff down a class hierarchy is a pain and
it makes it hard to use inheritance when you want to change some parameter
to a base class constructor farther down the line.

I wrote out a scenario where I really needed them in the comp.std.c++ article,
so please check it out.

--Jamshid Afshar
--jamshid@ccwf.cc.utexas.edu

jfw@rome.wpd.sgi.com (john fergus wilkinson) (08/21/90)

In article <9008201757.AA23899@sirius.risc.com>, ckl@SIRIUS.RISC.COM
(Carl K. Lim) writes:
> 
> Hello.  I have this problem: when I'm calling a virtual function from
a parent
> class's constructor, it fails to execute the derived class's function.  For
> example, in the following program, when B is declared, print() is called from
> A's constructor.  But instead of looking up the B::print(), A::print() is
> called instead.  Has anybody run into this kind of problem?  Is there a way
> to get around it?
> 
> 	#include <stdio.h>
> 
> 	class A
> 	{
> 	public:
> 	  A() { print(); }
> 	  virtual void print() { printf("A\n"); }
> 	};
> 
> 
> 	class B : public A
> 	{
> 	public:
> 	  B() {}
> 	  void print() { printf("B\n"); }
> 	};
> 
> 
> 	int main()
> 	{
> 	  B b;
> 	}

See Ellis and Stroustrup, Section 12.7.

jean@paradim.UUCP (Jean Pierre LeJacq) (08/21/90)

In article <9008201757.AA23899@sirius.risc.com>, ckl@SIRIUS.RISC.COM (Carl K. Lim) writes:
> 
> Hello.  I have this problem: when I'm calling a virtual function from a parent
> class's constructor, it fails to execute the derived class's function.  For
> ...

Virtual member functions can be called in constructors but the
function called will be the one defined in the constructor's
own class. This rule prevents access to partially constructed
objects. See [E&S: 294].

This also applies to destructors.

gwu@nujoizey.tcs.com (George Wu) (08/22/90)

     This question has been asked before.  According to Stanley Lippman's
"C++ Primer," virtual functions called from the constructor or destructor of
a base class will call the virtual function defined in the base class.  This
is by definition of the C++ language.

     The explanation is that at construction time, the derived object will
not yet be constructed, so the function cannot be from the derived class.
Likewise, in the destructor, the derived class will have already been
destroyed.

							George

----
George J Wu                           | gwu@tcs.com or ucbcad!tcs!gwu
Software Engineer                     | 2121 Allston Way, Berkeley, CA, 94704
Teknekron Communications Systems, Inc.| (415) 649-3752