#include #include using namespace std; class base { int i; public: base(int initial_i): i(initial_i) {} virtual ~base() {} virtual void f() {cout << "base::f\n";} virtual void g() const {cout << "base::g\n";} virtual int h(int n) const {cout << "base::h\n"; return i + n;} }; struct vtbl { //of a base object void (*ptr_to_destructor)(base *); void (*ptr_to_dynamic_destructor)(base *); void (*ptr_to_f)(base *); //ptr_to_f is a pointer to a function void (*ptr_to_g)(const base *); int (*ptr_to_h)(const base *, int); }; struct layout { //of a base object const vtbl *ptr_to_vtbl; int i; }; class derived: public base { int j; public: derived(int initial_i, int initial_j): base(initial_i), j(initial_j) {} void f() {cout << "derived::f\n";} int h(int n) const {cout << "derived::h\n"; return j + n;} }; void print(base *p); int main() { base b(10); cout << "sizeof b == " << sizeof b << "\n"; print(&b); derived d(20, 30); cout << "sizeof d == " << sizeof d << "\n"; print(&d); return EXIT_SUCCESS; } void print(base *p) { p->f(); p->g(); cout << p->h(40) << "\n"; //Unofficial; not portable. const layout& lay = reinterpret_cast(*p); const vtbl& v = *lay.ptr_to_vtbl; //This is what the calls in lines 54-56 actually do. (*v.ptr_to_f)(p); //v.ptr_to_f(p); (*v.ptr_to_g)(p); //v.ptr_to_g(p); cout << (*v.ptr_to_h)(p, 40) << "\n\n"; //v.ptr_to_h(p, 40) }