#include <cstdlib>
#include <iostream>
#include <stdexcept>
#include <vector>
using std::cout;
using std::endl;
enum
{
FIRE = 0x01,
WIND = 0x02,
LIGHTNING = 0x04,
SOIL = 0x08,
WATER = 0x10
};
class Skill // aka Jutsu =)
{
public:
// envelope constructor (see below)
Skill(int _type) throw (std::logic_error);
// destructor
virtual ~Skill()
{
if (mLetters.size() != 0)
{
cout << "~Skill()\t<- envelope destructor" << endl;
// virtual call in destructor!
erase();
}
else
{
cout << "~Skill()\t<- letter destructor" << endl;
}
for (size_t i = 0; i < mLetters.size(); i++)
delete mLetters[i]; // delete Letter for Envelope
// delete 0 for Letter
}
virtual void cast() const
{
for (size_t i = 0; i < mLetters.size(); i++)
mLetters[i]->cast();
}
virtual void show() const
{
for (size_t i = 0; i < mLetters.size(); i++)
mLetters[i]->show();
}
virtual void erase()
{
for (size_t i = 0; i < mLetters.size(); i++)
mLetters[i]->erase();
}
protected:
// letter constructor
Skill() : mLetters(NULL) { cout << "Skill()\t\t<- letter constructor" << endl; }
private:
Skill(const Skill &);
Skill & operator= (Skill &);
std::vector<Skill*> mLetters; // vector of pointers to letters
};
class FireSkill : public Skill
{
public:
~FireSkill() { cout << "~FireSkill()" << endl; }
virtual void cast() const { cout << "Katon!" << endl; }
virtual void show() const { cout << "FireSkill::show()" << endl; }
virtual void erase() { cout << "FireSkill:erase()" << endl; }
private:
friend class Skill;
FireSkill() {}
FireSkill(const FireSkill &);
FireSkill & operator=(FireSkill &);
};
class WoodSkill : public Skill
{
public:
~WoodSkill() { cout << "~WoodSkill()" << endl; }
virtual void cast() const { cout << "Mokuton!" << endl; }
virtual void show() const { cout << "WoodSkill::show()" << endl; }
virtual void erase() { cout << "WoodSkill::erase()" << endl; }
private:
friend class Skill;
WoodSkill() {}
WoodSkill(const WoodSkill &);
WoodSkill & operator=(WoodSkill &);
};
Skill::Skill(int _type) throw (std::logic_error)
{
cout << "Skill(_type)\t<- envelope constructor" << endl;
switch (_type)
{
case FIRE:
mLetters.push_back(new FireSkill);
break;
case SOIL | WATER:
mLetters.push_back(new WoodSkill);
break;
case FIRE | SOIL | WATER:
mLetters.push_back(new FireSkill);
mLetters.push_back(new WoodSkill);
break;
// ...
default:
throw std::logic_error("Incorrect type of element");
}
// virtual call in constructor!
cast();
}
int main()
{
std::vector<Skill*> skills;
try
{
skills.push_back(new Skill(FIRE));
skills.push_back(new Skill(SOIL | WATER));
skills.push_back(new Skill(FIRE | SOIL | WATER));
}
catch (std::logic_error le)
{
std::cerr << le.what() << endl;
return EXIT_FAILURE;
}
for (size_t i = 0; i < skills.size(); i++)
{
skills[i]->show();
delete skills[i];
}
return EXIT_SUCCESS;
}