2016-09-12 7 views
1

エンティティ/コンポーネントシステムをC++で動作させようとしています。これまでのところ大丈夫ですが、それほど多くはありませんが、私は問題に直面しています。ここ
は私の現在のコードである:C++コンポーネントシステムの問題

class Entity { 
public: 
    // [...] 
    template<typename T, typename ...Args> 
    bool AddComponent(Args... args) { 
     std::type_index tid = std::type_index(typeid(T)); 
     if (_Components[tid] == nullptr) { 
      _Components[tid] = std::make_shared<T>(args...); 
      return true; 
     } 
     return false; 
    } 

    template<typename T> 
    std::shared_ptr<T> GetComponent() { 
     // Issue here 
     std::type_index tid = std::type_index(typeid(T)); 
     return std::dynamic_pointer_cast<T>(_Components[tid]); // return nullptr if no component 
    } 

    template<typename T> 
    bool RemoveComponent() { 
     std::type_index tid = std::type_index(typeid(T)); 
     if (_Components.erase(tid) == 1) return true; 
     return false; 
    } 

    private: 
     std::map<std::type_index, std::shared_ptr<Component>> _Components; 
}; 

上記からわかるように、それはかなり簡単です、各成分は、ベースクラスComponentに由来し、以下のように使用される:

class Component; 
class MyComponent: public Component { 
    // [...] 
    MyComponent(int foo_): foo(foo_) {} 
    int foo; 
} 

Entity e; 
e.AddComponent<MyComponent>(42); 
std::cout << e.GetComponent<MyComponent>()->foo; // 42 
e.RemoveComponent<MyComponent>(); 
std::cout << e.GetComponent<MyComponent>()->foo; // Error 

エラーが論理と私は理由を理解していますが、私の質問は、削除されたComponentを呼び出すときにエラーを防ぐ方法であり、したがってプログラムをクラッシュさせずにnullptrですか?

シンプルなトライ/キャッチは十分ですか?ここにどのように実装する必要がありますか?

答えて

0

あなたはポインタをチェックすることができ、次のいずれか

auto ptr = e.GetComponent<MyComponent>(); 
if(ptr) ptr->foo(); 

またはHasComponentメソッドを追加します。

template<typename T> 
bool HasComponent() { 
    std::type_index tid = std::type_index(typeid(T)); 
    return _Components.find(tid) != _Components.cend(); 
} 

それはマップ内のnullptrを挿入しないとあなたはまた、そうGetComponentを変更することができます。

template<typename T> 
std::shared_ptr<T> GetComponent() { 
    std::type_index tid = std::type_index(typeid(T)); 
    return (_Components.find(tid) == _Components.cend()) ? nullptr : std::dynamic_pointer_cast<T>(_Components[tid]); 
} 
+0

「コンポーネント」がすべてのtに存在するかどうかを確認する以外に選択肢はありませんイム!そして、小さなことですが、 'HasComponent'は' std :: shared_ptr <> 'の代わりに真偽値を返してはいけませんか? – Usiten

+0

@Usitenうん、そう、コピー&ペーストエラー。ありがとうございました。 – skypjack