All the research papers about this subject (and there are hundreds
of research papers in the literature on this subject)
are done by people that missed your point. Interesting really.
Uh.
For instance:
http://www.cs.ucsb.edu/~urs/oocsb/papers/oopsla96.pdf
The Direct Cost of Virtual Function Calls in C++
That is just nonsense research. All those papers that try to improve
the direct cost of virtual function calls are just wrong...
No, they're quite right. They're answering, though, a VERY different
question.
Direct call:
puts("hello, world!\n");
Function pointer:
int (*foo)(const char *) = puts;
foo("hello, world!\n");
Virtual function call:
struct funcs {
struct funcs *next;
int (*foo)(const char *)puts_func;
};
struct foo {
struct funcs *functable;
char *s;
};
struct funcs stdio_functable = { NULL, puts };
struct foo greet_user = { &stdio_functable, "hello, world!\n" };
struct foo *greeter = &greet_user;
/* ... */
if (greeter->functable) {
struct funcs *vtable = greeter->functable;
while (vtable) {
if (vtable->puts_func) {
return vtable->puts_func(greeter->s);
}
vtable = vtable->next;
}
}
.... Oh, you're right, there's NO DIFFERENCE AT ALL between a virtual
function call using virtual function tables and a call through a function
pointer, I'm sure they're exactly the same thing and have identical
performance characteristics.
(Disclaimer: The above vtable interface was written on the fly
and is untested, but things of roughly this sort have been used in the
past, and are about the right mapping for the behavior of a virtual
function implementation, complete with the dynamic runtime calculation,
not just of what address to call, but where to find the address you plan
to call...)
And I will forget about the nonsense of heathfield that tries to make
a distinction between assembler mnemonics and machine code, or even
kuyper that says that all function calls are pointer function calls
with some citation from the C standard... (even saying that loading the
value of the call into the instruction pointer is a "pointer" call).
Of course you will.
Except that, in both cases, they're right. Assembler mnemonics are not always
1:1 with machine code in modern assemblers, and a call through an external
symbol is not necessarily noticably different between a symbol which the
linker maps to a function's address and a symbol which the compiler maps to a
variable holding a function's address.
-s