====== オーバーライドの演習(続き) ====== === ベースクラス(cChara型) === 戦士、魔法使い、盗賊の基本機能だけを持った抽象クラス\\ これ自体は、ベースとして使うからインスタンス化はしない(できない)\\ == cChara.h == #pragma once #include #include class cChara { public: //メンバ変数 std::string m_Name; int m_strength; //コンストラクタ cChara() :m_Name(""),m_strength(0){} cChara(std::string _name,int _strg) :m_Name(_name),m_strength(_strg){} //getter setter std::string getName() { return m_Name; } int getStrength() { return m_strength; } void setName(std::string _name) { m_Name = _name; } void setStrength(int _strength) { m_strength = _strength; } //基本機能 //・名乗る(自己紹介) 表示のみ ↓ void declare() {std::cout << "私は" << m_Name << "であーる!\n";} //・戦う(なぐる) void beat() {std::cout << "なぐります。ディクシ!\n";} //・防御(身を守る) void defence() {std::cout << "守ります。ガクブル!\n";} //・逃げる(逃亡) void escape() {std::cout << "逃げろー!\n";} //純粋仮想関数 for 特殊攻撃 virtual void specialAttack() = 0; }; == cChara.cpp == #include "cChara.h" //全部インラインにしちゃったからなんもない。。。 === 戦士型(cWorrior型) === cChara型を引き継ぎ、戦士としての機能を実装されたクラス。\\ 特に、追加機能はない。特殊攻撃も、戦士は特にないので寂しい。\\ ただし、仮想関数の実装自体は、何もしないという実装を行っている。\\ == cWorrior.h == #pragma once #include "cChara.h" class cWarrior : public cChara { //メンバの追加が必要なら書く public: //コンストラクタ cWarrior() :cChara(){} cWarrior(std::string _name, int _strength) :cChara(_name, _strength) {} //戦士は何も特殊攻撃しない。 void specialAttack() override { return; }; //あと、拡張したければ続けて書く }; == cWorrior.cpp == #include "cWarrior.h" //特に書くことなくなっちゃった === 魔法使い型(cWizard型) === cChara型を引き継ぎ、魔法使いとしての機能を実装されたクラス。\\ 特に、追加機能はない。特殊攻撃は、魔法を放つ(って表示するだけ)\\ == cWizard.h == #pragma once #include "cChara.h" class cWizard : public cChara { //メンバの追加が必要なら書く public: //コンストラクタ cWizard() :cChara() {} cWizard(std::string _name, int _strength) :cChara(_name, _strength) {} //魔法使いは魔法を使える。 //「攻撃魔法じゃー!」と叫んでください void specialAttack() override; //あと、拡張したければ続けて書く }; == cWizard.cpp == #include "cWizard.h" using std::cout; void cWizard::specialAttack() { cout << "魔法攻撃じゃー!\n"; } === 盗賊型(cThief型) === cChara型を引き継ぎ、魔法使いとしての機能を実装されたクラス。\\ 特に、追加機能はない。特殊攻撃は、魔法を放つ(って表示するだけ)\\ == cThief.h == #pragma once #include "cChara.h" class cThief : public cChara { //メンバの追加が必要なら書く public: //コンストラクタ cThief() :cChara() {} cThief(std::string _name, int _strength) :cChara(_name, _strength) {} //盗賊はお金を盗める //「戦士からお金を盗もうとした!」と表示 void specialAttack() override; //あと、拡張したければ続けて書く }; == cThief.cpp == #include "cThief.h" using std::cout; void cThief::specialAttack() { cout << "盗賊は戦士からお金を盗もうとした\n"; } === メイン関数(theMain.cpp) === 戦士、魔法使い、盗賊のインスタンスを作って呼び出す。\\ インスタンスは動的に作成しそのアドレスをvectorに追加する。\\ == theMain.cpp == #include #include "cChara.h" #include "cWarrior.h" #include "cWizard.h" #include "cThief.h" #include using std::vector; int main() { //cChara myhero; //戦士のオブジェクト //=cWarriorクラスのインスタンス を生成 //cWarrior myWorrior("フリオニール", 60); //myWorrior.declare();//名乗る! //myWorrior.beat(); //myWorrior.specialAttack(); ////魔法使いのオブジェクト //cWizard myMagician("ふじいあきら", 30); //myMagician.declare();//名乗る! //myMagician.beat(); //myMagician.specialAttack(); ////盗賊のオブジェクト //cThief myThief("ごえもん", 45); //myThief.declare();//名乗る! //myThief.beat(); //myThief.specialAttack(); //戦士のオブジェクト //単独の動的確保なら引数付きが呼べるんだよねぇ //cChara* myWorrior = new cWarrior("フリオニール", 60); //cChara* myMagician = new cWizard("ふじいあきら", 30); //cChara* myThief = new cThief("ごえもん", 45); vector charBox; //実体のあるものを追加 //charBox.push_back(myWorrior); //charBox.push_back(myMagician); //charBox.push_back(myThief); //オブジェクトを生成して、しかも追加 charBox.emplace_back(new cWarrior("フリオニール", 60)); charBox.emplace_back(new cWizard("ふじいあきら", 30)); charBox.emplace_back(new cThief("ごえもん", 45)); //charBox.size() for (int i = 0; i < charBox.size(); i++) { charBox[i]->declare(); charBox[i]->specialAttack(); } return 0; } ===== 練習問題 ===== キーボードから、以下のものを入力しキャラ\\ をvectorに追加していってください。\\ ①キャラの種類 1:戦士 2:魔法使い 3:盗賊\\ ↑これは switch-caseが必要だよね!\\ ②キャラの名前と、強さ\\ ③キャラの種類に0が入力されたらキャラ入力終了\\ キャラ入力終了したら、全キャラ名乗りを上げ特殊攻撃\\ を披露する。\\ ==== キャラ作るところまでのソースコード ==== #include #include "cChara.h" #include "cWarrior.h" #include "cWizard.h" #include "cThief.h" #include using std::vector; using std::cin; using std::string; int main() { int c_num;//キャラ番号 int cstren; string cname; vector heroBox; while (true) { printf("キャラの種類 1:戦士 2:魔法使い 3:盗賊 :"); cin >> c_num; if (c_num == 0)break; else { printf("キャラの名前を入力:"); cin >> cname; printf("キャラのちからを入力:"); cin >> cstren; cChara* p = nullptr; switch (c_num) { case 1: p = new cWarrior(cname, cstren); break; case 2: p = new cWizard(cname, cstren); break; case 3: p = new cThief(cname, cstren); break; default: break; } heroBox.push_back(p); } } return 0; } ==== vectorとイテレータ ==== //イテレータ:繰り返しのための変数 //ただし、ポインタだよ //vector::iterator theI; //for (auto theI : heroBox) //{ // theI->declare(); //} //rbegin(),rend()が、逆順 for (auto theI = heroBox.begin(); theI != heroBox.end(); theI++) { (*theI)->declare(); }