使用模板和/或typeof()实例化抽象基类类型的对象

时间:2016-12-18 14:42:40

标签: c# c++ templates generics

我试图在C ++中重写以下C#功能,但现在我需要考虑的更多:

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;
}
谷歌搜索和阅读模板确实有一些好处,但在这一点上,我认为我需要有经验的程序员对此进行观察。我在正确的轨道上吗?我得到了未解决的外部符号&#39;错误和C ++代码没有验证它是否正在创建正确类型的子类。我很欣赏这可能包含几个主题,但如果有人能帮我一把,那就太好了!

1 个答案:

答案 0 :(得分:0)

我认为正确的道路是尝试智能指针。这里有一些基于sfinae的方法与你在C#解决方案中做的有点相同:

#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]