It all depends on the implementation. But here are the answers to the simplest simple way using "vtables".
The Base class has a vtable pointer, so the base view is something like this pseudocode:
struct Base { void** __vtable; int a_number; }; void* __Base_vtable[] = { &Base::function1, &Base::function2 }; void __Base_ctor( struct Base* this_ptr ) { this_ptr->__vtable = __Base_vtable; }
The Derived class includes a subobject of the Base class. Since this is the place for vtable, Derived does not need to add another one.
struct Derived { struct Base __base; }; void* __Derived_vtable[] = { &Derived::function1, &Base::function2, &Derived::function4 }; void __Derived_ctor( struct Derived* this_ptr ) { __Base_ctor( &this_ptr->__base ); this_ptr->__base.__vtable = __Derived_vtable; }
"vtable for the base class", __Base_vtable in my pseudo-code, is necessary if someone tries new Base(); or Base obj; .
All of the above is complicated when using multiple inheritance or virtual inheritance ....
For the string b_ptr -> function4(); this is a compile-time error not related to vtables. When you add a Base* pointer, you can only use this pointer in the methods defined by class Base (since the compiler no longer “knows” whether it is Derived , a Base or another class). If Derived has its own data item, you cannot access it through this pointer. If Derived has its own member function, virtual or not, you cannot access it through this pointer.
aschepler
source share