Virtual inheritance in C++
Multiple inheritance is a powerful and tricky tool
Multiple inheritance is a powerful and tricky tool to use in C++ programming language but sometimes it needs to be handled with care.
Virtual inheritance is used when we are dealing with multiple inheritance but want to prevent multiple instances of same class appearing in inheritance hierarchy.
Consider below example :
From above example we can see that “A” is inherited two times in D means an object of class “D” will contain two attributes of “a” (D::C::a and D::B::a).
This problem is also known as diamond problem. Suppose Class “A” is having a function “func()” . Class “B” and class “C” both are inherited from “A” so they must be having function “func()”.
Class “D” is inherited from “B” and “C”, it contains double copy of that function. If we are calling this function through object of class “D” then ambiguity occurs because compiler gets confused whether it should call “func()” coming from “B” or from “C”.
Memory layout of class “D” object:
Supposed memory layout of class “D” object
If we are inheriting virtually like:
what are differences from previous situation:
- There will be new virtual base pointers which would be inserted by compiler when we are using virtual inheritance.
- This virtual base pointer will provide an indirect access to class “A” object and memory layout will look like:
Supposed memory layout of class “D” object after virtual inheritance.
Understanding offset details
Virtual base offset is 20 byte for “B” means we need to add 20 more bytes in vptr of B to get base object and same goes with “C” as we need to add 12 bytes for that.
3. When an object of class “D” is constructed it creates one class “C” object, one class “B” object and one class “A” object. Class “C” and class “D” are having virtual pointers which are helping in getting necessary offset details.
vptrs(virtual pointers) index a virtual table and there is a vptr for every virtual base of class. We use class “B” and class “C” object to index the virtual table through virtual pointer and get the required offset.
This offset will now be added in existing pointer to reach out the base class object.
How does it affect size of a class:
· vftr is virtual function pointer and vbptr is virtual base pointer.
· Size may vary on different machines here size of int considered as 4 byte.
size of A :: 8 byte
size of B :: 8 byte
size of C :: 20 byte ( 8 byte + 8 byte + 4 byte)
Here point to note that no vptr is included for the virtual function of “C” as this is how virtual function works,we want both base and derived class to share same vtable pointer which is pointing towards derived class.
size of A :: 8 bytes
size of B :: 20 byte(vftr of “B” (4 byte ) + vbptr(4 byte) + sizeof(b) + vfptr of “A”(4 byte) + sizeof(a))
size of C :: 12 byte
size of D :: 36 byte
vfptr of B (4 byte) + vbptr of B (4 byte) + size of (b) + vfptr of A(4 byte) + size of (a) + size of(c) + size of(d) + vfptr of A(4 byte)+ size of (a)
As we can see clearly in virtual inheritance base class will not be embedded in derived class only a pointer will be provided which is pointing to the base class object but in non virtual inheritance we can see a base class embedded in derived class.
This article was originally published by Nishi tyagi on medium.