晚上好,我第一次在这里问问题,所以请让我知道我是否犯了任何错误。

我和我的朋友最近开始编码基于组件的游戏引擎,遇到了困扰我数天的问题。
我有一个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/

10-11 22:57
查看更多