我正在尝试使用一个小的实体/组件系统来使用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 :(得分: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();
}
您还可以修改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]);
}