Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Sometimes, you just really need to see some code / diagrams :) Note that there is no mention of this implementation detail in the Standard.</p> <p>First of all, let's see how to implement methods in C++:</p> <pre><code>struct Base { void foo(); }; </code></pre> <p>This is similar to:</p> <pre><code>struct Base {}; void Base_foo(Base&amp; b); </code></pre> <p>And in fact, when you look at a method call within a debugger, you'll often see the <code>this</code> argument as the first parameter. It is sometimes called an implicit parameter.</p> <p>Now, on to the virtual table. In C and C++ it is possible to have pointers to function. A vtable is essentially a table of pointers to functions:</p> <pre><code>struct Base { int a; }; void Base_set(Base&amp; b, int i) { b.a = i; } int Base_get(Base const&amp; b) { return b.a; } struct BaseVTable { typedef void (*setter_t)(Base&amp;, int); typedef int (*getter_t)(Base const&amp;); setter_t mSetter; getter_t mGetter; BaseVTable(setter_t s, getter_t g): mSetter(s), mGetter(g) {} } gBaseVTable(&amp;Base_set, &amp;Base_get); </code></pre> <p>Now I can do something like:</p> <pre><code>void func() { Base b; (*gBaseVTable.mSetter)(b, 3); std::cout &lt;&lt; (*gBaseVTable.mGetter)(b) &lt;&lt; std::endl; // print 3 } </code></pre> <p>Now, on to the inheritance. Let's create another structure</p> <pre><code>struct Derived: Base {}; // yeah, Base does not have a virtual destructor... shh void Derived_set(Derived&amp; d, int i) { d.a = i+1; } struct DerivedBaseVTable { typedef void (*setter_t)(Derived&amp;,int); typedef BaseVTable::getter_t getter_t; setter_t mSetter; getter_t mGetter; DerivedBaseVTable(setter_t s, getter_t g): mSetter(s), mGetter(g) {} } gDerivedBaseVTable(&amp;Derived_set, &amp;Base_get); </code></pre> <p>And the use:</p> <pre><code>void func() { Derived d; (*gDerivedBaseVTable.mSetter)(d, 3); std::cout &lt;&lt; (*gDerivedBaseVTable.mGetter)(d) &lt;&lt; std::endl; // print 4 } </code></pre> <p>But how to automate this ?</p> <ul> <li>you only need one instance of a vtable per class having at least one virtual function</li> <li>each instance of the class will contain a pointer to the vtable as its first attribute (even though you can't really access it by yourself)</li> </ul> <p>Now, what happens in case of multi-inheritance ? Well, inheritance is very much like composition in term of memory layout:</p> <pre><code>| Derived | | BaseA | BaseB | | vpointer | field1 | field2 | padding? | vpointer | field1 | field2 | padding? | </code></pre> <p>There will thus be 2 virtual tables for <code>MostDerived</code>: one to change the methods from <code>BaseA</code> and one to change the methods from <code>BaseB</code>.</p> <p>Pure virtual functions are generally represented as a null pointer (simply) in the corresponding field.</p> <p>And finally, construction and destruction:</p> <p>Construction</p> <ul> <li><code>BaseA</code> is constructed: first the vpointer is initialized, then the attributes, then the body of the constructor is executed</li> <li><code>BaseB</code> is constructed: vpointer, attributes, body</li> <li><code>Derived</code> is constructed: replace the vpointers (both), attributes, body</li> </ul> <p>Destruction</p> <ul> <li><code>Derived is destructed</code>: body of the destructor, destroy attributes, put the base vpointers back</li> <li><code>BaseB</code> is destructed: body, attributes</li> <li><code>BaseA</code> is destructed: body, attributes</li> </ul> <p>I think it's pretty comprehensive, I'd be glad if some C++ gurus around there could review this and check I haven't made any stupid mistake. Also, if something is missing, I'd be glad to add it.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload