#include <iostream>
struct A
{
virtual void print (void) { std::cout << "A called." << std::endl; }
size_t x;
};
struct B : A
{
void print (void) { std::cout << "B called." << std::endl; }
};
// "Real" memory layout of A
struct Real_A
{
void * vtable;
size_t x_value;
};
// "Real" memory layout of B
struct Real_B : Real_A
{
size_t y_value;
};
// "Pseudo virtual table structure for classes with 1 virtual function"
struct VT
{
void * func_addr;
};
int main (void)
{
A * pa = new A;
pa->x = 15;
B * pb = new B;
pb->x = 20;
A * pa_b = new B;
pa_b->x = 25;
// reinterpret addrress of A and B objects as Real_A and Real_B
Real_A& ra(*(Real_A*)pa);
Real_B& rb(*(Real_B*)pb);
// reinterpret addrress of B object through pointer to A as Real_B
Real_B& rb_a(*(Real_B*)pa_b);
// Print x_values to know whether we meet the class layout
std::cout << "Value of ra.x_value = " << ra.x_value << std::endl;
std::cout << "Value of rb.x_value = " << rb.x_value << std::endl;
std::cout << "Value of rb.x_value = " << rb_a.x_value << std::endl;
// Print vtable addresses
std::cout << "VT of A through A*: " << ra.vtable << std::endl;
std::cout << "VT of B through B*: " << rb.vtable << std::endl;
std::cout << "VT of B through A*: " << rb_a.vtable << std::endl;
// Reinterpret memory pointed to by the vtable address as VT objects
VT& va(*(VT*)ra.vtable);
VT& vb(*(VT*)rb.vtable);
VT& vb_a(*(VT*)rb_a.vtable);
// Print addresses of functions in the vtable
std::cout << "FA of A through A*: " << va.func_addr << std::endl;
std::cout << "FA of B through B*: " << vb.func_addr << std::endl;
std::cout << "FA of B through A*: " << vb_a.func_addr << std::endl;
delete pa;
delete pb;
delete pa_b;
return 0;
}