比较派生类之间的类型

Comparing types between derived classes

本文关键字:类型 之间 派生 比较      更新时间:2023-10-16

我正在为一款游戏制作引擎,但我似乎无法解决以下问题。

所以,我有一个基组件类,所有不同的组件都是从它派生出来的。GameObject基本上是不同组件的容器。组件存储在包含指向基组件类的指针的vector中。现在我需要GameObject类拥有一个getComponent成员函数模板,它将从矢量中返回带有请求类型的组件。

更清楚:

class Component 
{
        /..../
};
class RigidBody : Component
{
        /..../
};
class Animation : Component
{
        /..../
};
class GameObject
{
public:
        template <class T>
        T* getComponent();
        void addComponent(Component*);
private:
        std::vector<Component*> m_components;
};
/...../
GameObject test;
test.AddComponent(new RigidBody());
test.AddComponent(new Animation());
Animation * animation = test.getComponent<Animation>();

或者在这些行之间。

为简单起见,假设vector保证具有我们要查找的组件,并且没有相同类型的组件。

由于vector中的指针是基组件类型,我如何检查它们最初是否为请求类型?提前感谢!

假设Component至少有一个虚函数(否则从它继承有什么意义,对吧?)你应该能够使用运行时类型信息(RTTI)和dynamic_cast做你需要做的事情,像这样:

template <class T> T* getFirstComponent() {
    for (int i = 0 ; i != m_components.size() ; i++) {
        T *candidate = dynamic_cast<T*>(m_components[i]);
        if (candidate) {
            return candidate;
        }
    }
    return nullptr;
}

回想一下,dynamic_cast<T*>只有在强制转换成功时才会返回一个非空值。上面的代码遍历所有指针,并选择dynamic_cast<T*>成功的第一个指针。

重要提示:虽然这应该可以让你的程序做你想做的事情,但考虑改变你的设计:不是按类型提取对象,而是给它们提供虚函数,让你以统一的方式使用它们。将不同类的对象放入一个容器中,只是在稍后的时间将它们分开,这是没有意义的。RTTI应该作为最后的手段使用,而不是作为主流工具,因为它使您的程序更难理解。

另一种有效的方法是单独存储各个组件,而不是存储在单个向量中,并且只有在需要统一处理对象时才获取向量。

不重要的注意事项:如果nullptr不能在您的系统上编译,请替换为return 0

在某些情况下,系统可能希望根据基类向量对派生类型进行分组,例如,在多线程的优化中。

我编写的一个系统使用多态性来创建用户定义的类型,以避免typeid或derived_class,这里是一些伪代码…

class BaseType {
public:
virtual int getType() = 0;
}
class ThisType : public BaseType {
public:
int getType() {return 1;};
}
class TypeMaster {
private:
std::vector<ThisType*> myObjects;
public:
void add(ThisType* bc){ myObjects.push_back(bc); };
}
std::map<int,TypeMaster*> masters;
std::vector<BaseType*> objects;
for(int i=0;i<objects.size();i++){
masters.find(objects[i].getType())->second.add(objects[i]);
}

你必须做一些工作来建立一个系统,但基本的东西是用来传达思想的。这段代码处理基对象的任意向量,并将它们附加到其master类型的向量上。

我的示例有一个执行池集合,其中包含多个类型master的实例,这意味着类型master不能被多态,因为在这种情况下,对象将无法在执行池中移动。

注意没有使用typeid或派生类。对我来说,使用本机类型的实现使它保持简单,而不需要导入臃肿的库或任何不必要的执行麻烦。您可以执行速度试验,但我总是发现简单的本机类型实现非常简洁。