I think the phrase "classes with virtual functions are implemented using vtables" is misleading.
The phrase makes it sound like classes with virtual functions are implemented "in order A" and classes without virtual functions are implemented "in order B".
In fact, classes with virtual functions, in addition to being implemented as classes, also have vtable. Another way to see this is with "vtables" to implement part of the "virtual function of the" class ".
More on how they work:
All classes (with virtual or non-virtual methods) are structures. The only difference between a structure and a class in C ++ is that, by default, members are public in structs and private in classes. Because of this, I will use the term βclassβ here to refer to both structures and classes. Remember that they are almost synonyms!
Data members
Classes (like structures) are just blocks of contiguous memory, where each element is stored in sequence. Please note that in some cases there will be gaps between members for reasons of processor architecture, so the block may be larger than the sum of its parts.
Methods
Methods or "member functions" are an illusion. Actually there is no such thing as a member function. A function is always a sequence of machine code instructions stored somewhere in memory. To make a call, the processor moves to this memory position and starts execution. We can say that all methods and functions are "global", and any indication to the contrary is a convenient illusion performed by the compiler.
Obviously, the method acts as if it belongs to a specific object, so it is clear that more is happening. To associate a specific method (function) call with a specific object, each member method has a hidden argument, which is a pointer to this object. The element is hidden in that you do not add it to your C ++ code yourself, but there is nothing magical about it - it is very real. When you say this:
void CMyThingy::DoSomething(int arg); {
The compiler really does this:
void CMyThingy_DoSomething(CMyThingy* this, int arg) { /do something }
Finally, when you write this:
myObj.doSomething(aValue);
the compiler says:
CMyThingy_DoSomething(&myObj, aValue);
No need for function pointers anywhere! The compiler already knows which method you are calling, so it calls it directly.
Static methods are even simpler. They do not have this pointer, so they execute exactly the same as you write them.
I.e! The rest is just convenient syntactic sugaring: the compiler knows which class the method belongs to, so it does not allow you to call a function without specifying which one. He also uses this knowledge to translate myItem to this->myItem when it is explicitly for this.
(yes, this is right: access to a member in a method is always performed indirectly using a pointer, even if you do not see it)
( Edit : deleted the last sentence and published separately so that it can be criticized separately)