CharaBasePlayerEnemyNewPlayer (CharaBase を継承)メインループより:
NewPlayer nPlayer("NewHero", Vector2D(50,250), Vector2D(1.0f,0), 1.0f); Enemy enemy("Monster", Vector2D(300,250), Vector2D(-5.0f,0), 1.0f); void Update() { nPlayer.Update(); enemy.Update(); } void Draw() { nPlayer.Draw(); enemy.Draw(); }
キャラに共通する情報:
name_:名前pos_:位置speed_:速度radius_:半径Update():移動処理Draw():描画処理
これらを CharaBase にまとめてある。
class CharaBase { public: CharaBase(string name, Vector2D pos, Vector2D speed, float radius); void Update(); void Draw(); void SetName(string name); void SetPosition(Vector2D pos); string GetName() const; Vector2D GetPosition() const; void SetSpeed(Vector2D speed); Vector2D GetSpeed() const; void SetRadius(float radius); double GetRadius() const; void SetChara(string n, Vector2D p, Vector2D v, double r); private: string name_; Vector2D pos_; Vector2D speed_; float radius_; };
void CharaBase::Update() { float dt = GetDeltaTime(); pos_.x = pos_.x + speed_.x * dt; pos_.y = pos_.y + speed_.y * dt; }
class NewPlayer : public CharaBase { public: NewPlayer(string name, Vector2D pos, Vector2D speed, float radius); void SayHello(); bool GetIsSayHello() { return isSayHello_; } private: bool isSayHello_; };
NewPlayer::NewPlayer(string name, Vector2D pos, Vector2D speed, float radius) : CharaBase(name, pos, speed, radius) , isSayHello_(false) { } void NewPlayer::SayHello() { isSayHello_ = true; }
ポイント:
NewPlayer のコンストラクタで CharaBase を初期化CharaBase が担当isSayHello_ のみ自分で管理継承では、基底クラスと同じ名前の関数を派生クラス側にも書くと、 「基底クラスの同名の関数が見えなくなる」ことがある。 この現象を 関数の隠蔽(いんぺい) という。
class Base { public: void Update(); }; class Derived : public Base { public: // ここに Update() を書いたらどうなる? // void Update(); };
→ Derived に Update() を追加してみる。
class Derived : public Base { public: void Update(); // Base::Update() と同じ名前 };
Derived d; d.Update(); // さて、どっちの Update() が呼ばれる?
→ 呼ばれるのは Derived::Update() (基底クラス Base の Update() は呼ばれない)
同じ名前の関数が派生クラスに書かれたことで、 基底クラスの Update() が名前の上で見えなくなる。
つまり:
Derived に関数を書く Base の同名関数は「隠れる」 この状態を 隠蔽(いんぺい) と呼ぶ。
最初の NewPlayer には Update() が実装されていない。
NewPlayer p("Hero", ...); p.Update(); // CharaBase::Update() が呼ばれる
ここでは、NewPlayer に Update() が無いので、
基底クラス CharaBase のものがそのまま使われる。
class NewPlayer : public CharaBase { public: void Update(); // ← 自分で実装 };
これを呼ぶと:
NewPlayer p("Hero", ...); p.Update(); // NewPlayer::Update() が呼ばれる
→ CharaBase::Update() は呼ばれない。
→ つまり、CharaBase::Update() が 隠蔽 されている。
隠蔽は、 「派生クラスに書いた同名関数が、基底クラスの同名関数を上書きしたように見せる仕組み」 であり、派生クラス型の変数で使うと”そう見える” という現象である。