keith@csli.Stanford.EDU (Keith Nishihara) (12/05/89)
When a class has a constructor and virtual functions, cfront1.2 generates code within the constructor function to set up the virtual function pointers. If a class is derived from such a base class, and one of the virtual functions is called from the base class constructor, the wrong virtual function is called, since during the execution of the base class constructor, the virtual function pointer table is set up as for the base class, and is not changed to show the derived class virtual functions until the derived class constructor is entered. Here is a real case: I have a hierarchical graphical editor in which the user manipulates prototypical objects in a layout. There are several types of primitive proto objects, and also compound proto objects (which represent occurrences of other layouts included within a higher level layout). These proto objects are derived from a base class `proto'. In order to support execution, part of the objects state is represented as an `instance' class; primitive proto classes create instance classes of themselves for each occurrence of a compound proto object representing the layout including the primitive proto. The implementation of this requires that each proto class define a virtual function Instantiate(context), which creates an instantiation in the given context. *All* derived classes are required to have at least one instance, defined within a context called top_level. The most natural way to achieve this is to have the constructor for the base class call the virtual function Instantiate(). However, at the time that this virtual function is called, the virtual function table is set up as if for the base class, and not for the derived class. class proto { public: proto() { ... Instantiate(top_level); ... } virtual void Instantiate(context) { } // Empty. ... }; class type_a_proto : public proto { public: virtual void Instantiate(context) { <create instance> } }; What happens is that the empty base class Instantiate function is called instead of the type_a_proto::Instantiate function when a new type_a_proto is created. (The fix, of course, is to call the Instantiate function from each derived constructor, instead of the base class. The problem is that it is then not possible to derive further sub classes of a derived type, as the intermediate class will create unwanted instantiations of themselves as their intermediate constructor functions are called.) Is this reasonable semantics for virtual function calling? I know that it is somewhat bogus to do anything with the derived object before its constructor has been called, but I do not find anything which says that it is illegal. In this case, my virtual function calls are not actually operating on the derived object, but are rather creating a parallel structure in a different context. Do other C++ compilers exhibit the same behaviour? Neil/. Neil%teleos.com@ai.sri.com ...decwrl!argosy!teleos!neil