c++组件系统问题

C++ Component System Issue

本文关键字:问题 系统 组件 c++      更新时间:2023-10-16

我试图得到一个小的实体/组件系统在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而不会使程序崩溃?

一个简单的try/catch就足够了吗?如何在这里实现呢?

您可以检查指针:

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();
}

你也可以修改GetComponent,这样它就不会在地图中插入nullptr:

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]);
}