maple
maple

Reputation: 1894

virtual function table of multiple inheritance

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?

Upvotes: 6

Views: 513

Answers (2)

Dr. Debasish Jana
Dr. Debasish Jana

Reputation: 7118

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

Upvotes: 1

Kerrek SB
Kerrek SB

Reputation: 476950

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.

Upvotes: 0

Related Questions