[gnu.g++.bug] 1.32.0 base initialization ignores virtuality

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