检查创建的对象的类是否派生自另一个类

时间:2016-01-09 17:30:32

标签: c++ game-engine

晚上好,我第一次在这里问一个问题,如果我犯了任何错误,请告诉我。

我和我的朋友最近开始编写一个基于组件的游戏引擎,并遇到了困扰我好几天的问题。 我有一个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读取(这个)作为Component *而不是AABBColliderComponent *。

我知道使用dynamic cast肯定会起作用,但我并不是真的倾向于使用它,而是希望学习使用某些核心模板。我现在的解决方法是让每个组件类都有自己的类名作为字符串返回,并检查类名。

如果有人在正确的方向指导我,真的很感激,谢谢!而且还想知道我是否应该在gamedev部门发布这个。

1 个答案:

答案 0 :(得分:1)

在运行时,您希望访问类型信息。

这意味着您需要一个RTTI系统。内置的通过动态强制转换和typeid公开。 Typeid不适合您的问题。

所以这意味着动态演员或推出自己的RTTI系统。

自己滚动的一种方法是维护要查询的所有类型的中央列表,然后使用模板和crtp填充vtable,其中包含有关给定对象的类型的信息。

另一个是完整的动态转换替换,其中每个类型都有足够的重新选择知识及其在类树中的位置,以填充您自己的手写rtti查询系统。

这些都是糟糕的想法,因为它类似于不知道如何驾驶汽车建议驾驶飞机前往杂货店的人。

最后一种方法是重新考虑您的设计。如果A是B并且与Bs一致地存储,则基于A而不是B的过滤是设计气味。考虑从类heirarchy中脱离的标签或某些内容来替换类型查询。