2016-12-18 7 views
0

私はC++で次のC#の機能を書き換えしようとしているが、多くはより多くの私が考える必要があり、今がありますよ:テンプレートおよび/またはtypeof演算()を使用して抽象基本クラス型のオブジェクトをインスタンス化

public abstract class Component 
{ 
} 

public class Entity 
{ 
    private List<Component> m_components = new List<Component>(); 

    public T AddComponent<T>() where T : Component 
    { 
     if (typeof(T).IsSubclassOf(typeof(Component))) 
     { 
      T newComponent = Activator.CreateInstance<T>(); 
      m_components.Add(newComponent); 
      return newComponent; 
     } 
     else 
     { 
      return null; 
     } 
    } 

    public Component AddComponent(Type t) 
    { 
     if (t.IsSubclassOf(typeof(Component))) 
     { 
      Component newComponent = (Component)Activator.CreateInstance(t); 
      m_components.Add(newComponent); 
      return newComponent; 
     } 
     else 
     { 
      return null; 
     } 
    } 
} 

これは限り私が得たようである:

class Component 
{ 
    Component() { } 
    ~Component() { } 
    void OnCreate() = 0; 
} 

class Entity 
{ 
public: 
    template<class N> void Entity::AddComponent() 
    { 
     N *newComponent = new N(); 
     m_components->push_back(newComponent); 
     newComponent->OnCreate(); 
    } 

private: 
    std::vector<Component*> *m_components; 
} 

は、グーグルやテンプレート上に読んでいくつかの良いをしましたが、この時点で私は経験豊富なプログラマはこの上で見る必要があると思います。正しい軌道にいるのですか?私は '未解決の外部シンボル'エラーが発生しているし、C + +コードは、それが正しいタイプのサブクラスを作成していることを検証していません。私はこれが2つのトピックを包含するかもしれないことを認めますが、誰かが私に手を差し伸べることができれば素晴らしいでしょう!

+2

は「typeof演算は、」C#はハック固有です。 C++には同様の構文がいくつかありますが、それらは悪いプログラミング方法とみなされます。ここでの正しい解決策は、仮想メソッドを適切に使用することです。 –

+0

@SamVarshavchikコメントをいただきありがとうございます。私は "typeof"がC#固有であり、使用するのが望ましくないことを知っています。おそらくそれを言及すべきではありません。あなたが答えを提供する瞬間があるなら、私はあなたの提案を聞くことに興味があるでしょう! –

答えて

0

私は、正しい道はスマートポインタを使って実験することだと思います。ここでは、あなたのC#ソリューションで行ったように、多少同じことをやって、いくつかのsfinaeベースのアプローチです:

#include <memory> 
#include <vector> 
#include <type_traits> 

class Component { 
public: 
    Component() { } 
    ~Component() { } 
    virtual void OnCreate() = 0; 
}; 

class Entity { 
public: 
    template<class T> std::enable_if_t<std::is_base_of<Component, T>::value> AddComponent() { 
     auto inserted = std::make_shared<T>(); 
     inserted->OnCreate(); 
     m_components.push_back(std::move(inserted)); 
    } 

    template<class T> std::enable_if_t<!std::is_base_of<Component, T>::value> AddComponent() { 
    } 
private: 
    std::vector<std::shared_ptr<Component>> m_components; 
}; 

class Component1: public Component { 
public: 
    void OnCreate() { } 
}; 
class Component2: public Component { 
public: 
    void OnCreate() { } 
}; 
class Component3 { 
public: 
    void OnCreate() { } 
}; 

int main() { 
    Entity e; 
    e.AddComponent<Component1>(); 
    e.AddComponent<Component2>(); 
    e.AddComponent<Component3>(); // won't add anything to your entity 
            // as Component3 is not a subclass of 
            // Component 
} 

[live demo]

+0

ありがとうございます。これにより、スピードアップするための良いトピックのような感じのテンプレートメタプログラミングについて読んでくれました。私はsfinaeのための余分なメソッドを除外すると思いますが、コンパイラのエラーはおそらくこの場合には正しいことです。 –

+0

sfinaeの代わりに関数を誤って使用した場合に専用のエラーメッセージを表示させたいのであれば、static_assert –

関連する問題