#include #include #include #include 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 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 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; }