#include <iostream>
using namespace std;
 
struct T { 
	virtual void foo();
	int i;
};
 
void displayT() {
	T ob;
	char *base = (char*)&ob; // spare me the new style casts
	int off_i = (char*)&ob.i - base;
	cout << "sizeof T is " << sizeof ob;
	cout << "\nsizeof i is " << sizeof ob.i;
	cout << "\ni is at offset " << off_i;
 
	string layout (sizeof ob, '*');
	layout.replace (off_i, sizeof ob.i, sizeof ob.i, 'i');
	cout << "\nlayout of T is \n" << layout << "\n";
}
 
struct U { 
	virtual void bar();
	long long l;
};
 
void displayU() {
	U ob;
	char *base = (char*)&ob;
	int off_l = (char*)&ob.l - base;
	cout << "sizeof U is " << sizeof ob;
	cout << "\nsizeof U::l is " << sizeof ob.l;
	cout << "\nl is at offset " << off_l;
 
	string layout (sizeof ob, '*');
	layout.replace (off_l, sizeof ob.l, sizeof ob.l, 'l');
	cout << "\nlayout of U is \n" << layout << "\n";
}
 
struct Der : T, U{ 
};
 
void displayDer() {
	Der ob;
	T &t = ob;
	U &u = ob;
	char *base = (char*)&ob;
	int off_i = (char*)&ob.i - base;
	int off_l = (char*)&ob.l - base;
	int off_T = (char*)&t - base;
	int off_U = (char*)&u - base;
 
	cout << "sizeof Der is " << sizeof ob;
	cout << "\nDer::i is at offset " << off_i;
	cout << "\nDer::l is at offset " << off_l;
	cout << "\nDer::T is at offset " << off_T;
	cout << "\nDer::U is at offset " << off_U;
 
	string layout (sizeof ob, '*');
	layout.replace (off_T, sizeof(T), sizeof (T), 'T');
	layout.replace (off_U, sizeof(U), sizeof (U), 'U');
	layout.replace (off_i, sizeof ob.i, sizeof ob.i, 'i');
	layout.replace (off_l, sizeof ob.l, sizeof ob.l, 'l');
	cout << "\nlayout of Der is \n" << layout << "\n";
}
 
struct Der2 : virtual T, U{ 
};
 
void displayDer2() {
	Der2 ob;
	T &t = ob;
	U &u = ob;
	char *base = (char*)&ob;
	int off_i = (char*)&ob.i - base;
	int off_l = (char*)&ob.l - base;
	int off_T = (char*)&t - base;
	int off_U = (char*)&u - base;
 
	cout << "sizeof Der2 is " << sizeof ob;
	cout << "\nDer2::i is at offset " << off_i;
	cout << "\nDer2::l is at offset " << off_l;
	cout << "\nDer2::T is at offset " << off_T;
	cout << "\nDer2::U is at offset " << off_U;
 
	string layout (sizeof ob, '*');
	layout.replace (off_T, sizeof(T), sizeof (T), 'T');
	layout.replace (off_U, sizeof(U), sizeof (U), 'U');
	layout.replace (off_i, sizeof ob.i, sizeof ob.i, 'i');
	layout.replace (off_l, sizeof ob.l, sizeof ob.l, 'l');
	cout << "\nlayout of Der2 is \n" << layout << "\n";
}
 
struct Der3 : virtual T, virtual U{ 
};
 
void displayDer3() {
	Der3 ob;
	T &t = ob;
	U &u = ob;
	char *base = (char*)&ob;
	int off_i = (char*)&ob.i - base;
	int off_l = (char*)&ob.l - base;
	int off_T = (char*)&t - base;
	int off_U = (char*)&u - base;
 
	cout << "sizeof Der3 is " << sizeof ob;
	cout << "\nDer3::i is at offset " << off_i;
	cout << "\nDer3::l is at offset " << off_l;
	cout << "\nDer3::T is at offset " << off_T;
	cout << "\nDer3::U is at offset " << off_U;
 
	string layout (sizeof ob, '*');
	layout.replace (off_T, sizeof(T), sizeof (T), 'T');
	layout.replace (off_U, sizeof(U), sizeof (U), 'U');
	layout.replace (off_i, sizeof ob.i, sizeof ob.i, 'i');
	layout.replace (off_l, sizeof ob.l, sizeof ob.l, 'l');
	cout << "\nlayout of Der3 is \n" << layout << "\n";
}
 
int main() {
	cout << "sizeof void* is " << sizeof(void*) << "\n";
	displayT();
	displayU();
	displayDer();
	displayDer2();
	displayDer3();
	return 0;
}