#include <iostream>
using namespace std;

class base
{
public:
	virtual ~base() { }
	virtual void hi() = 0;
	virtual size_t instance_size() = 0;
};

class A: base
{
public:
	virtual ~A() override { printf("*A destroyed*\n"); }
	virtual void hi() override { printf("Hi from A!\n"); }
	virtual size_t instance_size() override { return sizeof(*this); }
};

class B: base
{
public:
	string name;
	B(const string& name): name(name) { }
	virtual ~B() override { printf("*B destroyed*\n"); }
	virtual void hi() override { printf("Hi from B, %s!\n", name.c_str()); }
	virtual size_t instance_size() override { return sizeof(*this); }
};

class C: base
{
public:
	virtual ~C() override { printf("*C destroyed*\n"); }
	virtual void hi() override { printf("C says for you to go fuck yourself. >_<\n"); }
	virtual size_t instance_size() override { return sizeof(*this); }
};

unsigned char raw_queue[999];

int main() {
	unsigned char* push_ptr = raw_queue;
	{
		A* a_ptr = new (push_ptr) A;
		printf("A (sizeof=%zd) created at offset %zd.\n", sizeof(A), push_ptr - raw_queue);
		push_ptr += sizeof(A);
	}

	{
		B* b_ptr = new (push_ptr) B("Rika");
		printf("B (sizeof=%zd) created at offset %zd.\n", sizeof(B), push_ptr - raw_queue);
		push_ptr += sizeof(B);
	}

	{
		C* c_ptr = new (push_ptr) C;
		printf("C (sizeof=%zd) created at offset %zd.\n", sizeof(C), push_ptr - raw_queue);
		push_ptr += sizeof(C);
	}
	unsigned char* end_ptr = push_ptr;

	for (unsigned char* pop_ptr = raw_queue; pop_ptr < end_ptr; )
	{
		base* obj = (base*)pop_ptr;
		obj->hi();
		size_t obj_size = obj->instance_size();
		obj->~base();
		pop_ptr += obj_size;
	}
	return 0;
}