-1

私はモンスターとドラゴンがいるゲームに取り組んでいます。ドラゴンは、火を吐くことができることを除いて、モンスターができるすべてのことを行うことができます.

「モンスター」というタイプのクラスと、「ドラゴン」というモンスターを継承するクラスを作成しました。

次に、ドラゴンとモンスターの要素を含むプライベートメンバーベクトルを持つ「モンスター」と呼ばれるクラスがあります。

メインのゲーム ループでは、現在の要素がドラゴンの場合はベクトルを循環して火を吹き、ただのモンスターの場合は何もしません。

typeid() を使用してみましたが、現在の要素が単純なモンスターであろうとドラゴンであろうと、常に Monster* を返します。

これを行う方法はありますか、それともこの場合継承を使用しても意味がありませんか? ドラゴンクラスが継承せず、代わりにモンスターから独立した方が理にかなっているでしょうか?

アドバイスをいただければ幸いです。

4

5 に答える 5

3

あなたはこのようなことをすることができます。

class Monster {};
class Dragon : public Monster
{
  public:
    void BlowFire() {}
}

std::vector<Monster*> monsters; // Collection of monsters

for(auto it = monsters.begin(); it != monsters.end(); ++it)
{
    Dragon* pDragon = dynamic_cast<Dragon*>(*it); // Attempt to convert pointer
    if(pDragon)
    {
       pDragon->BlowFire(); // If it is indeed a Dragon, blow fire.
    }
}

しかし、クラスをもう少しうまく整理する必要があるようです。すべてのモンスタークラスにメソッドを持たせてみませんAttackか?このようにして、異なるモンスタータイプごとにメソッドをオーバーライドできます。

class Monster 
{
  public:
    virtual void Attack() {} // All monsters can attack
};

class Dragon : public Monster
{
  public:
    virtual void Attack() { // Do something special for a Dragon. }      
};

Monster myMonster;
Dragon myDragon;
myMonster.Attack(); // Generic monster attack.
myDragon.Attack(); // Special super dragon fire attack!
于 2012-09-05T12:11:24.357 に答える
1

考えられるアプローチは2つあります。仮想関数を使用するか、を使用しdynamic_castます。何もしないmonster仮想関数がある場合は、それをオーバーライドして、ドラゴンに適切なことを行うことができます。次に、すべてのオブジェクトに対してそれを呼び出すだけで、ドラゴンが火を吹きます。を使用すると、コードは次のようになります。blow_fire()dragonmonsterdynamic_cast

if (dragon *dragon_ptr = dynamic_cast<dragon*>(monster_ptr)) {
    dragon_ptr->blow_fire();
}

それは自然に成長しないので、それは一般的に悪いアプローチと見なされます。火を吹く可能性のある別の種類のモンスターを追加した場合は、別の種類のモンスターを追加する必要がありますdynamic_cast。仮想関数を使用すると、新しいタイプは仮想関数をオーバーライドするだけです。

于 2012-09-05T12:13:02.250 に答える
1

コンテナーにモンスター ポインターがある場合、(私の記憶によると) タイプ セーフな方法でそれらのポインターを介してアクセスできるのは、パブリック モンスター メンバーだけです。COM のようなインターフェイス ベースの設計に頼ってみると、モンスターの基底クラスに追加機能 (インターフェイスなど) を問い合わせることができます。サンプルを提供したいのですが、ランチタイムはもう終わりです。

于 2012-09-05T12:41:37.390 に答える
1

これが最善の方法であるというわけではありませんが、参考までに、オブジェクトのランタイム型が必要な場合に機能しないポインターtypeidを呼び出していました。必要に応じて実行時に機能しますが、多相型へのポインターを逆参照する必要があります。typeid

typeid(*monsterpointer)

そして、それは の実行時型を取得*monsterpointermonsterますdragon

ただし、typeidは正確な比較のみを目的としているため、ImpairedDragonから継承するという名前の別のクラスを追加するDragonと、typeidコードが壊れて動作しなくなります。したがってdynamic_cast、継承で機能するものを使用するか、仮想関数をうまく使用する方法を考えられる場合は、仮想関数を使用する必要があります。

于 2012-09-05T12:08:48.593 に答える
-2

空の(操作なしの)仮想blowFireを基本クラスに入れて、それを派生クラスの何かでオーバーライドするのはどうですか?

メソッドの名前をspecialAttackまたは同様の一般名に変更することをお勧めします。そのため、他の種類のモンスターに同様のメソッドを追加する必要はありません。

于 2012-09-05T12:11:46.857 に答える