#include <iostream>
#include <exception>
#include <vector>
#include <memory>
#include <string>

using namespace std;

class UmiMitHmotnostAZvuk {
public:
	virtual ~UmiMitHmotnostAZvuk() {};
	virtual float hmotnost() const = 0;
	virtual string zvuk() const = 0;
};

class Kocka : public UmiMitHmotnostAZvuk {
public:
	float hmotnost() const override {
		return 15;
	}
	string zvuk() const override {
		return "mnau";
	}
};

class Pes : public UmiMitHmotnostAZvuk {
public:
	float hmotnost() const override {
		return 15;
	}
	string zvuk() const override {
		return "haf";
	}
};

class Ptacek : public UmiMitHmotnostAZvuk {
public:
	float hmotnost() const override {
		return 1;
	}
	string zvuk() const override {
		return "kra";
	}
};

class Ohrada : public UmiMitHmotnostAZvuk
{
public:
	void pridej_zvire(std::unique_ptr<UmiMitHmotnostAZvuk> noveZvire) {
		zvirata.push_back(std::move(noveZvire));
	}
	vector<unique_ptr<UmiMitHmotnostAZvuk>> zvirata;
	template<typename Druh>
	size_t pocet_zvirat() const
	{
		size_t n = 0;
		for (const auto& z : zvirata)
			if (dynamic_cast<Druh*>(z.get()) != nullptr)++n;

		return n;
	}

	float hmotnost() const override
	{
		float hmotnost = 0;
		for( auto &z : zvirata)
		{
			hmotnost += z->hmotnost();
		}
		return hmotnost;
	}

	string zvuk() const override {
		string s;
		for (auto &z : zvirata)
		{
			s += z->zvuk();
		}
		return s;
	}

};





int main() {
	try {
		Ohrada o;
		o.pridej_zvire(make_unique<Ptacek>());
		o.pridej_zvire(make_unique<Pes>());
		o.pridej_zvire(make_unique<Ptacek>());
		o.pridej_zvire(make_unique<Kocka>());
		
		unique_ptr<Ohrada> o2(make_unique<Ohrada>());
		
		o2->pridej_zvire(make_unique<Ptacek>());
		o2->pridej_zvire(make_unique<Pes>());
		o.pridej_zvire(move(o2));

		for (const auto& z: o.zvirata) {
			cout << z->zvuk() << endl;
		}

		cout << o.pocet_zvirat<Ptacek>() << endl;

		cout << o.zvuk() << endl;
		cout << o.hmotnost() << endl;
	}
	catch (exception& e) {
		cerr << e.what() << endl;
		return 1;
	}
}
