C++ Object Memory Model

Summary

    // some examples:
    struct a { void foo(); };           // no need for virtual table
    struct b : a { virtual foo1(); };   // need vtable, and vptr
    struct c : b { void bar(); };       // no extra virtual table, 1 vptr (b) suffices
    struct d : b { virtual bar(); };    // 1 vtable, d extends b's vtable

    struct e : d, b {};                 // 2 vptr, 1 for the d and 1 for b
    struct f : virtual b {};            // 1 vptr, f reuse b's vptr to locate subobj b
    struct g : virtual b {};            // 1 vptr, g reuse b's vptr to locate subobj b
    struct h : f, g {};                 // 2 vptr, 1 for f, 1 for g
                                        // h can locate subobject b using f's vptr

Basically each sub-object of a type that requires its own dynamic dispatch (cannot directly reuse the parents) would need its own virtual table and vptr.

Only class which has virtual method will have vptr

Class with inheritance

class Base {
public:
    int baseVar;
};

class Derived : public Base {
public:
    double derivedVar;
    virtual void foo();
};

Memory Layout

Base Object

+---------------------+ 
| baseVar  | 
+---------------------+

Derived Object

+---------------------+ 
| vptr | // Pointing to Derived vTable
+---------------------+ 
| baseVar  |  // from Base 
+---------------------+ 
| derivedVar  |  //from Derived 
+---------------------+

Class with inheritance (Base is also virtual)

class Base {
public:
    int baseVar;
    virtual void foo();
};

class Derived : public Base {
public:
    double derivedVar;
    virtual void foo();
};

Memory Layout

Base Object

+---------------------+ 
| vptr | // Pointing to vTable for Base
+---------------------+ 
| baseVar  | 
+---------------------+

Derived Object

+---------------------+ 
| vptr | // Pointing to Derived vTable
+---------------------+ 
| baseVar  |  // from Base 
+---------------------+ 
| derivedVar  |  //from Derived 
+---------------------+

Class with multiple inheritance

class Base1 {
public:
    int baseVar1;
    virtual void foo();
};

class Base2 {
public:
    int baseVar2;
    virtual void foo();
};

class Derived : public Base, public Base2 {
public:
    double derivedVar;
    void foo() override;
};

Memory Layout

Base Object1

+---------------------+ 
| vptr | // Pointing to vTable for Base1
+---------------------+ 
| baseVar1  | 
+---------------------+

Base Object2

+---------------------+ 
| vptr | // Pointing to vTable for Base2
+---------------------+ 
| baseVar2  | 
+---------------------+

Derived Object

+---------------------+ 
| vptr | // Pointing to Derived vTable for Base1 (Base1 + Derived methods)
+---------------------+ 
| baseVar  | 
+---------------------+ 
| vptr | // Pointing to Derived vTable for Base2
+---------------------+ 
| baseVar2 | 
+---------------------+ 
| derivedVar  |  //from Derived 
+---------------------+

References

https://shaharmike.com/cpp/vtable-part1/
https://stackoverflow.com/questions/3342035/how-many-vptr-will-a-object-of-classuses-single-multiple-inheritance-have