6

The sample code are as follow:

class A
{
public:
    int k;
    virtual int f();
};
class B:public virtual  A
{
public:
    virtual int a();
};
int main()
{
    cout<<sizeof(A)<<sizeof(B);
}

It prints

8 12

It seems class B has its own new virtual function table.

If class A changes to:

class A
{
public:
    virtual int f();
};

It prints

4 4

Could anyone explain the reason?

Niall
  • 30,036
  • 10
  • 99
  • 142
maple
  • 1,828
  • 2
  • 19
  • 28
  • 4
    If the base is stateless, then you don't actually ever need to locate the base subobject, so you need less information in the derived class. – Kerrek SB Aug 27 '14 at 09:01
  • @KerrekSB make that an answer ;) – Quentin Aug 27 '14 at 09:02
  • @KerrekSB Do you mean that it is the compiler that do a optimization for the derived class to make it simple? – maple Aug 27 '14 at 09:05
  • @KerrekSB, That doesn't seem so obvious. If we have C which also inherit virtualy from A and D which inherit from B and C. Casting a D to B and then A has to have to same pointer as casting the D to C and then A, even if A has no state. – AProgrammer Aug 27 '14 at 09:05
  • 3
    You are looking at the object size, not the v-table size. sizeof(A) = v-table pointer + k, sizeof(B) = v-table pointer of A + v-table pointer of B + k. Which can be optimized in the 2nd snippet since virtual inheritance no longer matters. – Hans Passant Aug 27 '14 at 09:10
  • With VS2012 I get different results: 8 16 with k and 4 12 without. Optimization was '/O2' (max speed). '/O1' (min size) leads to the same results. Together with Hans' comment this makes even sense to me. – TobiMcNamobi Aug 27 '14 at 09:21
  • Related to [virtual-tables-and-memory-layout-in-multiple-virtual-inheritance](http://stackoverflow.com/questions/11603198/virtual-tables-and-memory-layout-in-multiple-virtual-inheritance) – Jarod42 Aug 27 '14 at 09:26

2 Answers2

1

In your subclass B, B is a virtual subclass of A. Thus, B has a separate vtbl pointer (4 bytes) on top of what you have on subobject A. Thus,

sizeof(B object) 
= sizeof(A object) + sizeof (vtbl pointer of B)
= sizeof(int) + sizeof (vtbl pointer of A) + sizeof (vtbl pointer of B)
= 4 + 4 + 4
= 12

And,

sizeof(A object)
= sizeof(int) + sizeof (vtbl pointer of A)
= 4 + 4
= 8

If B is a normal subclass of A,

 sizeof(B object) 
    = sizeof(A object) 
    = sizeof(int) + sizeof (vtbl pointer of A) 
    = 4 + 4
    = 12

For empty class A, minimum size allocated for sizeof A object is sizeof pointer of vtbl = 4 And since A is empty in terms of instance data, virtual inheritance for empty class does not add to size of the object

Dr. Debasish Jana
  • 6,980
  • 4
  • 30
  • 69
0

In the context of class inheritance, "virtual" means "determined at runtime". There are two separate things that can be virtual, and that an implementation must implement somehow:

  • virtual functions, for which the actual function that is to be called has to be determined at runtime: x.f()who is f? Common implementations involve tables of function pointers.

  • virtual inheritance, in which the virtual base subobject is not known until runtime. The implementation must provide a mechanism for locating the actual base object: x.a = 10where is a? Common implementations for this involve pointer offset computations.

If a virtual base class has no state (this is similar, but not equivalent, to "is empty"), then the second use case becomes vacuous. Since there are no data members whose location must be determined dynamically, the implementation doesn't need to generate any information for doing this, nor do objects need to store the relevant references.

One popular C++ ABI, the Itanium ABI, describes in detail how virtuality is implemented. There is also this popular article explaining this implementation.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • You can cast to the common base class using two inheritance paths and the pointers have to compare equal, so the adjustment has to be done. So even if there is no data whose location must be determined at run-time, that pointer to nothing else than a vptr has. – AProgrammer Aug 27 '14 at 11:16