My understanding of vtables is that, if I have a class Cat with a virtual function speak() with subclasses Lion and HouseCat, there is a vtable which maps speak() to the correct implementation for each Subclass. So a call
cat.speak()
Compiles to
cat.vtable[0]()
That is, a look-up in the vtable position 0 and a call of the function pointer in this position.
My question is: What happens on multiple inheritance?
Let's add a class Pet. Pet has virtual functions speak() and eat(). HouseCat extends Pet, while Lion does not. Now, I need to make sure that
pet.eat()
Compiles as
pet.vtable[1]()
That is vtable[0] needs to be speak(). Pet.eat needs to be slot 1. That is because cat.speak() needs to access slot 0 in the vtable, and if, for a HouseCat, slot 0 happens to be eat, this will go horribly wrong.
How does the compiler ensure that the vtable indexes fit together?
B
derives fromA
, thenB
is-aA
: it means every detail ofA
is reproduced inB
, notably the vptr and vtable. Then ifB
derives fromA1
,A2
,A3
, then every detail ofAx
is reproduced inB
, so it will end up with (at least) as many vptr as the base subobjects. – Thyroideat
must be in position 1.Pet
could have a vtable specifying{eat, speak}
whileCat
keeps a vtable specifying{speak}
. – Castoff