#include <iostream>
#include <cstdlib>
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<const layout &>(*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)
}