识别多态对象的替代方法?

时间:2012-11-03 03:23:53

标签: c++ dynamic polymorphism

我一直在网上搜索,如果两个多态对象是同一类型,或者多态对象是一个类型,我似乎找不到任何替代方法进行比较。这是因为我要在我正在创建的游戏中实现一个实体系统。

除了使用宏或强制转换(演员不是这样做的可移植方法)之外,我还没有找到另一种方法。目前这就是我识别对象的方式,有没有更有效或更有效的方法呢? (不使用C ++ RTTI)

我把它粘贴在pastebin上,因为在这里粘贴它太麻烦了。 http://pastebin.com/2uwrb4y2

只是因为你仍然不明白我想要实现的目标,我会试着解释一下。游戏中的实体就像游戏内部的对象(例如玩家或敌人),它具有附加到其上的组件,这些组件是实体的数据。实体系统中的系统将游戏的数据和逻辑结合在一起。

例如,如果我想在屏幕上显示模型,它将类似于:

World world; // Where all entities are contained

// create an entity from the world, and add
// some geometry that is loaded from a file
Entity* e = world.createEntity();
e->add(new GeometryComponent());
e->get<GeometryComponent>()->loadModel("my_model.obj"); // this is what I want to be able to do


world.addSystem(new RenderingSystem());

// game loop
bool isRunning = true;
while(isRunning) 
{
   pollInput();
   // etc...      

   // update the world
   world.update();
}

编辑: 这是一个用Java编写的框架,主要完成我想要做的事情。 http://gamadu.com/artemis/tutorial.html

3 个答案:

答案 0 :(得分:3)

请参阅std::is_polymorphic。我相信也有提升。

  

如果T是多态类(即,声明或继承至少一个虚函数的类),则提供成员常量值等于true。对于任何其他类型,值为false。

http://en.cppreference.com/w/cpp/types/is_polymorphic


编辑:

为什么你不能在你的例子中这样做?

Entity* e = world.createEntity();
GemoetryComponent* gc = new GeometryComponent();
gc->loadModel("my_model.obj");
e->add(gc);

在剥离类型信息之前创建结构。

答案 1 :(得分:0)

如果你决定不使用C ++的内置RTTI,你可以通过从包含虚方法的基类派生所有类来自己重新实现它:

class Base {
public:
    virtual string getType() = 0;
};

然后,每个派生类都需要使用返回不同字符串的版本重载此方法:

class Foo : public Base {
public:
    string getType() { return "Foo"; }
};

然后,您可以简单地比较每个对象上调用getType()的结果,以确定它们是否属于同一类型。如果您事先知道将要创建的所有派生类,则可以使用枚举而不是string

答案 2 :(得分:0)

Entity* e = world.createEntity();
e->add(new GeometryComponent());
e->get<GeometryComponent>()->loadModel("my_model.obj"); 
   // this is what I want to be able to do

首先简单:可以添加所有组件的基本类型,否则您将无法执行e->add(new GeometryComponent())。我假设这个特定的基数至少有一个virtual函数,在这种情况下,简单的解决方案是将get实现为:

template <typename T>
T* get() {
   return dynamic_cast<T*>(m_component); // or whatever your member is
}

问题是你不想使用RTTI,但是你没有提供理由。常见的误解是RTTI ,如果是这种情况,请考虑分析以查看是否属于您的情况。在大多数情况下,dynamic_cast<>的缓慢并不重要,因为dynamic_cast在您的程序中很少发生。如果dynamic_cast<>是一个瓶颈,你应该重构,这样你就不会使用它,这将是最好的解决方案。

更快的方法,(再次,如果你有一个性能瓶颈,你应该重新设计,这会使它更快,但设计仍然会被打破)如果你只想允许获得完整类型的对象会使用typeid的组合来测试相等的类型,并使用static_cast来执行向下转换:

template <typename T>
T* get() {
   if (typeid(*m_component)==typeid(T))
      return static_cast<T*>(m_component);
   else
      return 0;
}

这是dynamic_cast的穷人版本。它会更快,但它只会让你转换为完整的类型(即指向的对象的实际类型,而不是它的任何中间基础)。

如果您愿意牺牲所有正确性(或者没有RTTI:即没有虚函数),您可以直接执行static_cast,但如果该对象不属于该类型,则会导致未定义的行为。< / p>