0

私はウェブ全体を検索してきましたが、2 つのポリモーフィック オブジェクトが同じタイプであるか、またはポリモーフィック オブジェクトがタイプであるかを比較する別の方法が見つからないようです。これは、現在作成中のゲーム内にエンティティ システムを実装するためです。

マクロを使用するかキャストを使用する以外に、これを行う別の方法は見つかりませんでした(キャストは移植可能な方法ではありません)。現在、これは私がオブジェクトを識別する方法ですが、これを行うためのより効率的または効果的な方法はありますか? (C++ RTTI を使用しない場合)

ここに貼り付けるのは面倒なので、ペーストビンに貼り付けました。 http://pastebin.com/2uwrb4y2

そして、私が達成しようとしていることをまだ正確に理解していない場合に備えて、説明しようと思います. ゲーム内のエンティティは、ゲーム内のオブジェクト (プレイヤーや敵など) のようなもので、コンポーネントがアタッチされています。これらのコンポーネントはエンティティのデータです。エンティティ システム内のシステムは、ゲームのデータとロジックを結合するものです。

たとえば、モデルを画面に表示したい場合は、次のようになります。

World world; // Where all entities are contained

// create an entity from the world, and add
// some geometry that is loaded from a file
Entity* e = world.createEntity();
e->add(new GeometryComponent());
e->get<GeometryComponent>()->loadModel("my_model.obj"); // this is what I want to be able to do


world.addSystem(new RenderingSystem());

// game loop
bool isRunning = true;
while(isRunning) 
{
   pollInput();
   // etc...      

   // update the world
   world.update();
}

編集:これは、主に私がやりたいことを行うJavaでプログラムされたフレームワークです。 http://gamadu.com/artemis/tutorial.html

4

3 に答える 3

3

を参照してくださいstd::is_polymorphic。ブーストにもそれがあると思います。

T がポリモーフィック クラス (つまり、少なくとも 1 つの仮想関数を宣言または継承するクラス) の場合、true に等しいメンバー定数値を提供します。その他のタイプの場合、値は false です。

http://en.cppreference.com/w/cpp/types/is_polymorphic


編集:

あなたの例でこれを行うことができないのはなぜですか?

Entity* e = world.createEntity();
GemoetryComponent* gc = new GeometryComponent();
gc->loadModel("my_model.obj");
e->add(gc);

型情報を削除する前に構造体を作成してください。

于 2012-11-03T03:26:20.283 に答える
0
Entity* e = world.createEntity();
e->add(new GeometryComponent());
e->get<GeometryComponent>()->loadModel("my_model.obj"); 
   // this is what I want to be able to do

First the simple: there is a base type to all of the components that can be added, or else you would not be able to do e->add(new GeometryComponent()). I assume that this particular base has at least one virtual function, in which case the trivial solution is to implement get as:

template <typename T>
T* get() {
   return dynamic_cast<T*>(m_component); // or whatever your member is
}

The question says that you don't want to use RTTI, but you fail to provide a reason. The common misundertandings are that RTTI is slow, if that is the case, consider profiling to see if that is your case. In most cases the slowness of dynamic_cast<> is not important, as dynamic_casts should happen rarely on your program. If dynamic_cast<> is a bottleneck, you should refactor so that you don't use it which would be the best solution.

A faster approach, (again, if you have a performance bottleneck here you should redesign, this will make it faster, but the design will still be broken) if you only want to allow to obtain the complete type of the object would be to use a combination of typeid to tests the type for equality and static_cast to perform the downcast:

template <typename T>
T* get() {
   if (typeid(*m_component)==typeid(T))
      return static_cast<T*>(m_component);
   else
      return 0;
}

Which is a poor man's version of dynamic_cast. It will be faster but it will only let you cast to the complete type (i.e. the actual type of the object pointed, not any of it's intermediate bases).

If you are willing to sacrifice all correctness (or there is no RTTI: i.e. no virtual functions) you can do the static_cast directly, but if the object is not of that type you will cause undefined behavior.

于 2012-11-04T18:50:21.493 に答える
0

C++ の組み込み RTTI を使用しないことに決めた場合は、仮想メソッドを含む基本クラスからすべてのクラスを派生させることで、自分で再実装できます。

class Base {
public:
    virtual string getType() = 0;
};

次に、すべての派生クラスは、このメソッドを個別の文字列を返すバージョンでオーバーロードする必要があります。

class Foo : public Base {
public:
    string getType() { return "Foo"; }
};

getType()次に、各オブジェクトの呼び出し結果を単純に比較して、それらが同じタイプであるかどうかを判断できます。string作成されるすべての派生クラスを前もって知っている場合は、列挙型の代わりに列挙型を使用できます。

于 2012-11-03T04:43:29.577 に答える