2016-06-01 10 views
4

私はC++を学んでおり、エンティティコンポーネントシステムを作成したいと思っています。そのためには、エンティティにコンポーネントを追加するときにコンポーネントのタイプを知る必要があります。 Javaでは、私はちょうどこのような何かをするでしょう:Javasクラス<?> C++で同等

Class<?> someClass = myComponent.class; 

私はC + +で何かできますか?私はtypeid(myComponent)を試しましたが、このような状況では動作しません。

ExtComponent* extended = new ExtComponent(); 
Component* base = dynamic_cast<Component>(extended); 
std::cout << typeid(base).name(); 

これは "class Component"を返しますが、このような状況では "class ExtComponent"を返すものが必要です。どうすればいいの?

+0

あなたがしたいのは、 'std :: cout << typeid(* base).name()'です。 baseは 'Component *'であり、決して変更されません。基礎となる仮想タイプに基づいて、どのタイプのベースポイントがタイプを変更できるか。また、あなたのダイナミックキャストには 'dynamic_cast 'が必要です。 –

+0

アップキャストにdynamic_castは必要ありません。 'Component * base = extended;'で十分です。 – user2079303

+0

@quipoは喜んで助けます。他に注意しなければならないことは: 'new'を使って動的オブジェクトを作成することはめったに良い考えではありません。自動変数を優先する。また、 'type_info :: name'は実装定義の文字列を返します。それは "クラスExtComponent"であるか、 "_ZN9ExtComponent"またはそれ以外のものである可能性があります。異なるコンパイラ間で文字列が同一であることや、読みやすい名前であることに頼ることはできません。 – user2079303

答えて

6

私はあなたが正しく理解したい場合はオブジェクトの動的タイプを取得したいと思います。 (変数自体の種類、しかし、その変数(本当に)を指しものにしない)

TYPEIDがあるために動作します:タイプIDが適用された場合

N3337 5.2.8/2グレー値式が多型クラス型(10.3)である場合、結果はを表すstd :: type_infoオブジェクトに を参照します。(1.8)(つまり、動的 タイプ)glvalueが参照する[...]

ので、ちょうど作るために、そして自分のやりたいことになる代わりに、仮想基本クラスのいくつかの仮想関数を()を追加します。

また、あなたは(それは反対しない、ポインタのためtype_infoを返すため)ポインタでないオブジェクトにtypeidを適用する必要があります:

Base *b = new Base; 
... 
typeid(*b); //not typeid(b) 
+0

N3337?どうしてですか[N4594](https://github.com/cplusplus/draft/raw/master/papers/n4594.pdf)? –

+0

ありがとうございました。 – qwipo

2

種類を扱う、すべてがコンパイル時に解決されなければなりません。実行時にそれらを解決することはできません。これがC++の仕組みです。式のタイプを変更するには、テンプレートを処理する必要があります。

さまざまな種類のインスタンスの束を格納するコンテナを作成する場合は、その型を覚えておく必要があります。テンプレートは各1つの自分自身のアドレスと異なる機能をインスタンス化しているので、我々はタイプの一意のIDを生成するためにそれを使用することができます:

template<typename> 
void type_id(){} 

using type_id_t = void(*)(); 

さて、あなたは保存し、安全な方法で取得するためにこれを使用することができます。ここではstd::anyを使用しますが、C++ 17の機能にアクセスできない場合はboost::anyに置き換えることができます。

struct Entity { 
    template<typename T> 
    void assign(T component) { 
     components[type_id<T>] = component; 
    } 

    template<typename T> 
    T& retrieve() { 
     return std::any_cast<T>(components[type_id<T>]); 
    } 

private: 
    std::map<type_id_t, std::any> components; 
}; 

ここに移動します。

Entity entity; 

entity.assign(MyClass{}); 

MyClass& mc = entity.retreive<MyClass>(); 

これはエンティティのごみと簡単な実装です。通常、エンティティとコンポーネントをメモリにパックし、エンティティマネージャを使用してそれらのライフタイムを管理しようとします。

関連する問題