[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.16.1 Virtual Base Classes with Virtual Tables

In case of virtual bases, the code is even more complicated. Constructors and destructors need to know whether they are "in charge" of the virtual bases, and an implicit integer `__in_chrg' for that purpose.

 
struct A{
  int i;
  virtual void bar();
  void call_bar(){bar();}
};

struct B:virtual A{
  B();
  int j;
  virtual void bar();
};

B::B(){
  call_bar();
}

struct C{
  int k;
};

struct D:C,B{
  int l;
  virtual void bar();
};

When constructing an instance of B, it will have the following layout: `vbase pointer to A', `j', `A virtual table', `i'. On a 32-bit machine, downcasting from `A*' to `B*' would need to subtract 8, which would be the thunk executed when calling `B::bar' inside `call_bar'.

When constructing an instance of D, it will have a different layout: `k', `vbase pointer to A', `j', `l', `A virtual table', `i'. So, when downcasting from `A*' to `B*' in a `D' object, the offset would be `12'.

This means that during construction of the `B' base of a `D' object, a virtual table is needed which has a `-12' thunk to `B::bar'. This is only needed during construction and destruction, as the full object will use a `-16' thunk to `D::bar'.

In order to implement this, the compiler generates an implicit argument (in addition to __in_chrg): the virtual list argument __vlist. This is a list of virtual tables needed during construction and destruction. The virtual pointers are ordered in the way they are used during construction; the destructors will process the array in reverse order. The ordering is as follows:

The compiler emits a virtual table list in a variable mangled as __vl.classname.

Class with virtual bases, but without pvbases, only have the __in_chrg argument to their ctors and dtors: they don't have any vfields in the vbases to initialize.

A further problem arises with virtual destructors: A destructor typically has only the __in_chrg argument, which also indicates whether the destructor should call operator delete. A dtor of a class with pvbases has an additional argument. Unfortunately, a caller of a virtual dtor might not know whether to pass that argument or not. Therefore, the dtor processes the __vlist argument in an automatic variable, which is initialized from the class' vlist if the __in_chrg flag has a zero value in bit 2 (bit mask 4), or from the argument __vlist1 if bit 2 of the __in_chrg parameter is set to one.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

This document was generated by system on December, 2 2004 using texi2html