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