#include <iostream>
#include <string>
#include <vector>
#include <memory>
#include <algorithm>
using namespace std;

class pet {
	string name_;
protected:
	string name() const { return name_; }
	virtual void do_make_sound() const = 0;
public:
	pet(const char* name) : name_(name) {}
	virtual ~pet() { cout << name() << " dctor." << endl; }
	void make_sound() const { do_make_sound(); }
};

class dog : public pet {
protected:
	virtual void do_make_sound() const { cout << name() << ": わんわんおー" << endl; }
public:
	dog(const char* name) : pet(name) {}
};

class cat : public pet {
protected:
	virtual void do_make_sound() const { cout << name() << ": にゃんにゃんおー" << endl; }
public:
	cat(const char* name) : pet(name) {}
};



int main()
{
	vector<shared_ptr<pet>> pets;

	vector<shared_ptr<cat>> cats;
	cats.push_back(make_shared<cat>("タマ"));
	cats.push_back(make_shared<cat>("ミケ"));
	cats.push_back(make_shared<cat>("Kitty"));
	for_each(cats.begin(), cats.end(), [](shared_ptr<cat> pet) {pet->make_sound(); });
	{
		vector<shared_ptr<dog>> dogs;
		dogs.push_back(make_shared<dog>("ポチ"));
		dogs.push_back(make_shared<dog>("コロ"));
		dogs.push_back(make_shared<dog>("Lassie"));
		for_each(dogs.begin(), dogs.end(), [](shared_ptr<dog> pet) {pet->make_sound(); });

		pets.push_back(cats[0]);
		pets.push_back(dogs[0]);
		pets.push_back(cats[1]);
		pets.push_back(dogs[1]);

	}
	
	for_each(pets.begin(), pets.end(), [](shared_ptr<pet> pet) { pet->make_sound(); });
	cout << "That's it." << endl;
}
