There is this code:
#include <iostream>
class Base
{
int x;
};
class Derived : virtual public Base
{
int y;
};
int main()
{
std::cout << sizeof(Derived) << std::endl; // prints 12
return 0;
}
I have read that when some class is virtually inherited then there is created empty vtable for class Derived, so memory layout is as follows:
Derived::ptr to empty vtable
Derived::y
Base::x
and it is 12 bytes. The question is - what is purpose of this empty vtable if there are not any virtual methods and how is it used?
Derivedneeds some way to know where theBasesubobject is. With virtual inheritance, the relative location of the base class is not fixed with respect to the location of the derived class: it may be located anywhere in the full object.Consider a more typical example involving diamond inheritance.
Here, both
B1andB2derive virtually fromA, so inC, there is exactly oneAsubobject. BothB1andB2need to know how to find thatAsubobject (so that they can access theamember variable, or other members ofAif we were to define them).This is what the vtable is used for in this case: both
B1andB2will have a vtable that contains the offset of theAsubobject.To demonstrate what a compiler might do to implement the above diamond inheritance example, consider the following class layouts and virtual tables, generated by the Visual C++ 11 Developer Preview.
and the following vtables:
Note that the offsets are relative to the address of the vtable, and note that for the two vtables generated for the
B1andB2subobjects ofC, the offsets are different.(Also note that this is entirely an implementation detail--other compilers may implement virtual functions and bases differently. This example demonstrates one way that they are implemented, and they are very commonly implemented this way.)