4

私のプログラムには、Entityという名前のクラスがあります。別のクラスInvaderはEntityを継承します。4種類の侵入者が欲しいので、Invaderから継承するクラスInvader1、Invader2、Invader3、Invader4を宣言します。次に、次のようなすべての侵入者を格納するために、エンティティポインタタイプのベクトルを宣言します。

entities.push_back(new Invader4());
entities.push_back(new Invader3());
entities.push_back(new Invader2());
entities.push_back(new Invader1());
entities.push_back(new Invader0());

実行時にエンティティの要素のタイプを確認すると、

typeid(*entities->at(index)) 

4種類の侵入者のうち​​の1つを返す可能性があります。エンティティには、エンティティを継承する他のオブジェクトもあります。したがって、オブジェクトのタイプがInvaderであるかどうかを確認したいだけです。それが、Invader1、Invader2などであるかどうかは知りたくありません。

どうすればこれを達成できますか?

4

4 に答える 4

6

C ++でこれを行うには多くの方法がありますが、基本的な問題は、多形であると想定されるコンテナー内の要素のクエリを開始する必要がある場合、ポリモーフィズムを使用するという考えをあきらめる可能性があることです。多形要素のコレクションを持つことの全体的なポイントは、それらをすべて同じように扱うことができるということです。したがって、aがあるvector<Entity*>場合は、その要素のみをEntity*sとして扱う必要があります。Invaderでいくつかのような関数を呼び出す必要がある場合Entityは、のコンテナも保持することをお勧めしますInvader*(元のコンテナと同じポインタを使用します)。

于 2012-05-07T14:13:34.597 に答える
3

dynamic_cast<Invader*>(entities->at(index))が返されないかどうかを確認できますNULLNULLポインタが、から派生したクラスのオブジェクトを指していない場合にポインタが生成されるためInvader)。

いくつかのドキュメントについては、このリンクを参照してください。

于 2012-05-07T13:55:01.167 に答える
2

Invaderから継承するクラスを作成しますEntityInvader1Invader2などのクラスをから継承しますInvader

次に、をvirtual bool IsInvader() const;返すfalseを追加できます。EntitytrueInvader

于 2012-05-07T13:57:56.977 に答える
1

この質問をするだけで、通常、インターフェイスに仮想関数が実際に欠落していることを意味します。

あなたが次のようなものを持っている場合:

if (myEntity->Type() == TypeInvader)
{
  static_cast<Invader*>(myEntity)->invade();
}

追加することでほぼ確実にリファクタリングできます

virtual void tryInvade() {/* normally, entities don't invade*/}

あなたのエンティティと

virtual void tryInvade() {invade(); /*but invaders do!*/}

インベーダークラスで。

もう1つのオプションは、エンティティのタイプを決して「失う」ことはありません。このような場合に仮想関数を使用したくない場合は、基本クラスのポインターを参照してこれらのエンティティを格納するのではなく、実際に使用するクラスへのポインターとして格納する必要があります。つまり、後で要求するのではなく、エンティティのタイプを保持するだけです。これはおそらく、リスコフの置換原則のそれぞれのストレージに違反しているため、継承を使用すべきではなかったことを示しています。

于 2012-05-07T14:12:54.497 に答える