https://nimrod.blog/posts/what-does-cpp-object-layout-look-like/
No inheritance
- non-static class member variables are laid out in declaration order, with padding and alignment
- alignof(type): returns the alignment of a type
- alignas(int constexpr or type): specifies alignment requirement for a var
- can use with class/class member var/var
- attribute(packed): disregard padding and alignment and put member vars consecutive…
Single inheritance
- base class is stacked on top of derived class
- if there is vptr, it is put before base class to make sure vptr is still accessible with object slicing…
inside vtable
- vcall offset
- vbase offset
- delta: offset to top
- always = 0 for single inherence
- useful with object slicing with multi inheritance… (<=0 delta)
- typeinfo pointer
- function pointers for virtual functions
- ABI defines “__cxa_pure_virtual” as the placeholder
- pure virtual functions: func ptr to “__cxa_pure_virtual”
- vptr in instantiated objects point to the begin of this list, not the top of vtable!
- if dtor is virtual, there will be 2 dtor func ptr included: complete obj dtor and deleting dtor
- 1 for objects on stacks, 1 for objects on heap
- 3 types of destructor:
- base object destructor: runs the destructors for non-static data members and non-virtual direct base classes
- the compiler generates the function to execute code in the object destruction then call other destructors (of member var and base classes).
- complete object destructor: runs base object destructor and the destructors for the virtual base classes
- deleting destructor: runs complete object destructor and calls the appropriate deallocation function (e.g. op delete)
Multi inheritance

- Parent classes will be stacked on top of each other. Each subobject will retains its own vptr if exists.
- vtable for each subobject will point differently…
- subobject destructor implemented using thunk: offset back to the true base then call the true destructor