virtual function table of multiple inheritance
Asked Answered
L

2

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?

Letterperfect answered 27/8, 2014 at 8:59 Comment(7)
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.Chimborazo
@KerrekSB make that an answer ;)Icarus
@KerrekSB Do you mean that it is the compiler that do a optimization for the derived class to make it simple?Letterperfect
@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.Koralie
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.Tempe
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.Marriott
Related to virtual-tables-and-memory-layout-in-multiple-virtual-inheritanceKikuyu
B
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

Bargeman answered 27/8, 2014 at 9:29 Comment(0)
C
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.

Chimborazo answered 27/8, 2014 at 9:26 Comment(1)
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.Koralie

© 2022 - 2024 — McMap. All rights reserved.