#include <iostream>
#include <list>
#include <memory>
using namespace std;

struct Base
{
	int b;
	virtual void vypisB() { cout << b << endl; }
};

struct P : Base
{

	void vypisB() override { cout << "uplne jine b" << b << endl; }
};

class Zvire
{
      public:
	virtual void zvuk() = 0;
	virtual ~Zvire(){};
};

class Tulen : public Zvire
{
	int kulatost;

      public:
	Tulen(int k)
	  : kulatost(k)
	{}
	~Tulen() { cout << "zvuk miziciho tulene: ahoj" << endl; }
	void zvuk()
	{
		cout << "Tulen kulatosti " << kulatost << "rika: ";
		cout << "opi[qprg]qaegdaf" << endl;
	}
};

class Had : public Zvire
{
	int delka;

      public:
	Had(int d)
	  : delka(d)
	{}
	~Had() { cout << "zvuk miziciho hada: ahoj" << endl; }
	void zvuk()
	{
		cout << "Had delky " << delka << "rika: ";
		cout << "ssssssssss" << endl;
	}
};
class Jedlik : public Zvire
{
	unique_ptr<Zvire> potrava;

      public:
	Jedlik(unique_ptr<Zvire> a)
	{
		potrava = move(a);
		cout << "Jedlik sa najedol" << endl;
	}
	~Jedlik() { cout << "zvuk miziciho jedlika: ahoj" << endl; }
	void zvuk()
	{
		cout << "Chramst: ";
		potrava->zvuk();
	}
};

class Pavilon : public Zvire
{
	list<unique_ptr<Zvire>> zvierata;

      public:
	void pridaj_zviera(unique_ptr<Zvire> z) { zvierata.push_back(move(z)); }
	void zvuk()
	{
		cout << "zvuk z pavilonu" << endl;
		for (auto& z : zvierata)
			z->zvuk();
		cout << "koniec zvuku z pavilonu" << endl;
	}
};

int
main()
{
	list<unique_ptr<Zvire>> zoo;
	// unique_ptr<Zvire> t = make_unique<Tulen>(124);
	unique_ptr<Pavilon> p = make_unique<Pavilon>();
	p->pridaj_zviera(make_unique<Tulen>(124));

	zoo.push_back(make_unique<Tulen>(124));
	zoo.push_back(make_unique<Had>(13));
	zoo.push_back(make_unique<Jedlik>(make_unique<Had>(15)));
	zoo.push_back(move(p));
	for (auto& i : zoo) {
		i->zvuk();
	}
	int pocet_tulenov = 0;
	for (auto& i : zoo) {
		Tulen* t = dynamic_cast<Tulen*>(i.get());
		if (!t) {
			continue;
		}
		pocet_tulenov++;
	}
	cout << pocet_tulenov << endl;
}

#if 0
void f(Base* b)
{
	b->vypisB();
}

int main() {
	P p;

	
	p.b = 11;
	
	f(&p);
	cout << sizeof(p) << endl;

	Zvire z;
	return 0;
}
#endif
