I’d say most of the C++ implementations work similar to this (and probably the first
implementations, that compiled into C, produced code like this):
struct ClassVTABLE {
void (* virtuamethod1)(Class *this);
void (* virtuamethod2)(Class *this, int arg);
};
struct Class {
ClassVTABLE *vtable;
};
Then, given an instance Class x
, calling the method virtualmethod1
for it is like x.vtable->virtualmethod1(&x)
, thus one extra dereference, 1 indexed lookup from the vtable
, and one extra argument (= this
) pushed onto the stack / passed in registers.
However the compiler probably can optimize repeated method calls on an instance within a function: since an instance Class x
cannot change its class after it is constructed, the compiler can consider the whole x.vtable->virtualmethod1
as a common sub-expression, and move it out of loops. Thus in this case the repeated virtual method calls within a single function would be equivalent in speed to calling a function via a simple function pointer.