大家晚上好,我第一次在这里提问,所以如果我犯了任何错误,请告诉我。
我和我的 friend 最近开始编写一个基于组件的游戏引擎,遇到了一个困扰我好几天的问题。 我有一个实体类,它存储附加到它的组件列表,并且我已经能够通过模板成功地向实体添加和删除组件。简化代码如下所示:
class Component
{
type_index getType() { return std::type_index(typeid(*this)); }
template<class T>
bool Component::IsInheritedFrom(){
return std::is_base_of<T, std::remove_pointer<decltype(this)>>::value;
}
class Entity
{
std::vector<Component*> ComponentList;
template<class T>
T* getComponent(){
//Just iterate through the vector list and use each component's getType function to check
}
template<class T>
T* removeComponent(){
//Same as above
}
template<class T>
T* getBaseComponent(){
//Iterate and use component's IsInheritedFrom function to check
}
}
问题是在开发游戏时,我们创建了一些碰撞器组件,以及一个碰撞器管理器:
class ColliderComponent : public Component
{
void CheckCollision(Entity* toCheck)
{
//Unable to get component
auto comp = toCheck->getBaseComponent<ColliderComponent>();
}
}
class SphericalColliderComponent : public ColliderComponent
{}
class AABBColliderComponent : public ColliderComponent
{}
对于具有球形或 AABB 碰撞体的实体,IsInheritedFrom 函数无法按预期运行,因为继承的碰撞体作为 Component* 存储在 vector 列表中,因此当调用 IsheritedFrom 函数时,decltype 读取 ( this) 作为 Component* 而不是 AABBColliderComponent*。
我知道使用 dynamic cast
确实有效,但我不太愿意使用它,并希望有一些硬核模板来学习使用。我目前的解决方法是让每个组件类都有自己的类名作为字符串返回,然后检查类名。
如果有人能给我指点正确的方向,我将不胜感激,谢谢!并且还想知道我是否应该将其发布到游戏开发部门。
最佳答案
在运行时,您需要访问类型信息。
这意味着您需要一个 RTTI 系统。内置的通过动态转换和 typeid 公开。 Typeid 不适合您的问题。
所以这意味着动态转换,或推出您自己的 RTTI 系统。
自己动手的一种方法是维护一个包含您要查询的所有类型的中央列表,然后使用模板和 crtp 将有关给定对象的类型的信息填充到 vtable。
另一个是完全动态转换替换,其中每种类型都被赋予足够的关于它的知识及其在类树中的位置,以填充您自己的手写 rtti 查询系统。
这两个都是坏主意,因为它类似于一个不会开车的人提议造一架飞机去杂货店。
最后一种方法是重新考虑您的设计。如果 A 是 B 并且与 Bs 统一存储,那么基于是 A 而不是 B 的过滤就是设计味道。考虑使用标签或脱离类层次结构的东西来替换类型查询。
关于c++ - 检查创建的对象的类是否派生自另一个类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34696657/