Virtual function calls are commonly implemented using a virtual method table. Compilers typically create one such table for each class in your program, and give each object a pointer to the virtual table that corresponds to its class when the object is instantiated (this pointer is referred to as vptr
). This way, the object "knows" exactly which function to call when you call a virtual method regardless of its static type.
As I mentioned above, normally each class gets its own virtual method table. The paragraph you cite says that if a class derives from e.g. 5 base classes, each of which also derives from 5 other classes, then the virtual table for this class should end up being a merged version of all 25 virtual tables of the base classes. This would be kind of wasteful, so the compiler might decide to only merge the 5 virtual tables from the "immediate" base classes into the derived class's virtual table, and keep the vptr
s to the other 20 virtual tables stored as a hidden member inside the class (which would now have 21 vptr
s total).
The benefit in doing this is that you don't need to reserve memory repeating the same information every time a class with a virtual table is derived from. The downside is that you complicate the implementation (e.g. when calling a virtual method, the compiler now has to somehow figure out which one of the vptr
s points to the table that tells it which method to call).
Regarding the second question, I 'm not sure what exactly you are asking. This code assumes that the vptr
is the very first item in the memory layout of object of that class (which is practically true often, but a horrible hack since nowhere does it say that virtual methods are even implemented using a virtual table; there might not even be a vptr
), fetches the second item from the table (which is a pointer to a member function of the class) and runs it.
Expect fireworks if even the slightest thing goes wrong (e.g.: there was no vptr
, the vptr
's structure is not what the person who wrote the code expected, a later version of the compiler decides to change how it stores the virtual table, the method pointed to has a different signature, etc etc etc).
Update (addressing the comments):
Let's say we have
class Child : Mom, Dad {};
class Mom : GrandMom1, GrandDad1 {};
class Dad : GrandMom2, GrandDad2 {};
In this case, Mom
and Dad
are the immediate base classes ("first-born", but the term is misleading).
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…