晚上好,我第一次在这里问问题,所以请让我知道我是否犯了任何错误。
我和我的朋友最近开始编码基于组件的游戏引擎,遇到了困扰我数天的问题。
我有一个Entity类,用于存储与其相连的组件列表,并且能够通过模板向Entity成功添加和删除组件。简化的代码如下所示:
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
}
}
问题在于,在开发游戏时,我们创建了一些对撞机组件以及colliderManager:
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 *存储在向量列表中,因此,当调用IsheritedFrom函数时,decltype读取(this)为而不是AABBColliderComponent *。
我知道使用
dynamic cast
肯定可以工作,但是我不太愿意使用它,并希望可以学习一些硬性模板。我现在拥有的当前解决方法是,让每个组件类都有其自己的类名称以字符串形式返回,然后检查类名称。如果有人给我正确的方向指示,我将非常感谢,谢谢!并且还想知道我是否应该将其发布在gamedev部门中。
最佳答案
在运行时,您想访问类型信息。
这意味着您需要一个RTTI系统。内置的通过动态强制转换和typeid公开。 Typeid不适合您的问题。
因此,这意味着动态投射或滚动自己的RTTI系统。
自己滚动的一种方法是维护要查询的所有类型的中央列表,然后使用模板和crtp向vtable填充有关给定对象是什么类型的信息。
另一个是全面的动态转换替换,其中每种类型都有足够的相关知识及其在类树中的位置,以填充您自己的手写rtti查询系统。
这两个都是坏主意,因为它类似于一个不知道如何驾驶拟建飞机去杂货店的人。
最后一种方法是重新考虑您的设计。如果A是B并与Bs均匀存储,则基于A而不是B的过滤是设计气味。考虑使用标记或与类层次结构不同的内容来替换类型查询。
关于c++ - 检查创建的对象的类是否从另一个类派生,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/34696657/