dove@UUNET.UU.NET (Webster Dove) (04/14/89)
The following program prints base base base derived and should (I think) print base base derived derived This happens with cfront also. Why? (Please reply via mail) // -*- C++ -*- #include <stream.h> class base { public: virtual void foo() { cout << "base"; } base() { foo(); } }; class derived : base { public: virtual void foo() { cout << "derived"; } derived() {}; }; main() { base x; x.foo(); derived y; // Prints "base" should print "derived". y.foo(); }
grunwald@flute.cs.uiuc.edu (04/16/89)
re: your example you get base/base/base/derived this is correct. when entering a constructor, it first sets the vtable pointer to the vtables correct for this subclass. your derived class calls the base constructor, the base constructor installs its vtable, you do the call (to base::foo) and then your derived constructor sets the table. if you had called `foo' within the derived constructor, it would print `derived'. this is, to me, somewhat annoying, although the `logical' thing to do. the base constructor gets called *before* a derived constructor. calling derived functions when the constructor is not finished can't make sense, unless those functions only involve the base member variables. of course, this is a pain in the butt, because you want to be able to define things like virtual `size' functions to return the `true size' of the class. If you could do this, you could specify a class ``StorageAllocator'' which does block storage allocation properly for subclasses. perhaps what's needed is *virtual class functions*, i.e., if you said: class base { virtual static size() } class foo : base { virtual static size() } class bar : base { virtual static size() } calling ``size'' in base::base would call foo::size if it's of type foo and bar::size if it's of type bar. you'd have to place restrictions on the operations in the functions; perhaps only access to static member variables would be enough. In many ways, this is a logical extension of static member functions. you'd have to have two vtables; one which points to static member virtuals and one which points to normal virtuals, because you'd need to set them at different times. is this construct useful for anything else? the only case it's useful is if you're trying to determine some property of the derived class within the constructor. I'd say it's probably easier to just pass things (like `size') in as a parameter. -- Dirk Grunwald Univ. of Illinois grunwald@flute.cs.uiuc.edu