Let's say we have this interface in Java-like language:
interface Animal {
public int getAge();
}
interface Tamable {
public void tame();
}
Those interfaces is being implemented by classes:
class Cat implements Animal { // Cats are not tamable
public int getAge() { // this method is somewhere in memory (e.g. at 0xf000)
// ...
}
}
class Dog implements Animal, Tamable {
public int getAge() { // this method is somewhere in memory (e.g. at 0xf008)
// ...
}
public void tame() { // this method is somewhere in memory (e.g. at 0xf00e)
// ...
}
}
When passing interface Tamable
to some another method like this:
void pet(Tamable tamable) {
tamable.tame(); // <-- this call
// ...
}
How do we know which memory adress to jump to when calling tame()
? How are VMT (Virtual Method Table) implemented in this case?
The only way I can imagine them being implemted is some hash table, but this seems like it would make virtual dispatch very slow.
If VMT is just array/vector of function pointers, then how does compiler know what offset to use to get function pointer tame()
on class Dog
, when dispatching the call, when at compile-time it cannot be resolved whenever tamable
would be Dog
or Cat
?
(Note: Java was used just as example, I am looking for more general answer)
Any suggestions would be helpful. All the resources I found on the Internet were very vague about how VMT are implemented and how keys for VMT are gained.
For each implemented interface an object of class contains pointer to this interface's VMT (so called vptr
). Whenever you call a function which takes interface as a parameter (like pet
in your case) a pointer to vptr
is passed under the hood (vptr
is not passed directly because compiler will also need to pass location to object when calling interface methods through vptr
).
Each VMT is just an array of function pointers. The index of each method in this array is statically assigned by compiler based on the order of methods in interface declaration.