[comp.lang.c++] Virtual functions in constructors

arn@apple.com (Arn Schaeffer) (04/01/89)

I am not sure if this message actually made it to the network outside of 
Apple Computer.  If it did, I'm sorry for the reposting.  Otherwise, here it is:

I have a question concerning what the proper semantics of virtual function 
calls appearing in a constructor (or destructor).  It does not appear that 
the "correct" behavior for this is documented.  There are atleast three 
possibilities concerning how these calls should be interpreted.  I have 
not been able to determine what the behavior is supposed to be.  I am 
interested in which option is the correct behavior and why.  


Option #1:
Do not allow virtual function calls in constructors.

Option #2:
Because base classes are initialized before derived classes, a virtual 
function appearing in the constructor of a base class should call the 
virtual function as it was defined for the base class.  This is the 
behavior that I see right now.  I suppose that the reasoning behind this 
is that since derived classes are uninitialized, a call to a virtual 
function (as defined in the derived class) could do a very bad thing like 
access fields defined in the derived class.  I also imagine that this is 
easier to implement since the vtable is fixed up along the way back down 
the class hierarchy to point to the correct virtual function definition as 
we construct the object.  This implementation seems to defy one of the 
invariants of the language concerning the invocation of virtual functions. 
Further, if you wanted to call the virtual function defined for the base 
class, you could do it with the scope resolution operator.

Option #3:
Virtual functions always invoke the definition in the derived class.  If 
you would like to call a specific function, use the scope resolution 
operator to achieve the behavior discussed in option
two.  It appears that this interpretation is convenient if the 
implementation of the base class can change based on the derived class.  
Certainly,  a somewhat degenerate use of parameterized types could present 
a partial solution to this problem; however, I'm wondering if there are 
other classes of problems that could benefit from this interpretation.

Thank-you for your help.

arn schaeffer (arn@apple.com)

The opinions expressed are not necessarily those of Apple Computer.

ark@alice.UUCP (Andrew Koenig) (04/01/89)

In article <1129@internal.Apple.COM>, arn@apple.com (Arn Schaeffer) writes:

> Option #1:
> Do not allow virtual function calls in constructors.

> Option #2:
> Because base classes are initialized before derived classes, a virtual 
> function appearing in the constructor of a base class should call the 
> virtual function as it was defined for the base class.

> Option #3:
> Virtual functions always invoke the definition in the derived class.

Option 2 is correct.

Imagine a base class B and a class D derived from B.  Constructing
a D object involves first constructing the B that is part of it.

If a virtual function in B were called by B::B(), and it were
to a member of D, that would be executing a member of D before
initializing the D object.

Because D::D() can control which particular constructor of B
gets called, it is possible to make B behave differently when
constructed as part of a D than when constructed independently.
It is even possible to protect it:

	class B {
	public:
		B();
	protected:
		B(int);
		// and so on
	};

	class D: public B {
	public:
		D(int n): (n) {
			/* stuff */
		}
		// and so on
	};

The (n) in the definition of D::D(int) is the argument to
be handed to the base class (B).  Because B::B(int) is
protected, it is impossible to create a B object directly
from an int (although bugs in some C++ implementations may
let it slip by anyway).


Incidentally, option 1 is practically impossible to enforce:

	class B:

	extern void fudge(B*);

	class B {
	public:
		B() { fudge(this); }
		// and so on
	};

If fudge() is separately compiled, how can the compiler know that
it should not call any virtual functions?
-- 
				--Andrew Koenig
				  ark@europa.att.com