【问题标题】:What is the best way to dynamically check the types of a class that uses variadic inheritance?动态检查使用可变继承的类的类型的最佳方法是什么?
【发布时间】:2015-02-09 17:31:49
【问题描述】:

我正在为使用可变参数模板构建游戏对象的 2D 游戏引擎编写实体组件系统。这是对象类,它只是所有组件的容器。我删除了不相关的东西。

template<class ... Components>
class Object : public Components...{
public:
    Object(Game* game) : Components(game)...{

    }
};

组件由对象继承,但我试图找到检查这些组件类型的最佳方法,以便它们能够正确地相互通信。例如,物理组件将包含对象的更新位置。 Drawable 组件需要获取该位置,以便可以在世界上正确的位置进行绘制。我想向 Object 添加一个更新函数,用于更新每个组件并在当前组件之间传输可以/需要传输的任何信息。

【问题讨论】:

  • 您能否阐明您的要求,例如使用更多代码?我可能遗漏了一些东西,因为如果您只需要 Drawable 组件来使用物理协调,只需编写类似 void Object::update() {this-&gt;draw(*this);} 的内容,假设您有 void Drawable::draw(const Physics &amp;)。只要右DrawablePhysics 在可变参数Components... 中,这将起作用

标签: c++ templates variadic-templates


【解决方案1】:

多态是你想要的。 只需像这样制作所有组件:

public Object
{
 enum TYPE{
 COMPONENT,,
 GAMEOBJECT,
 ETC,,,
};
Object(TYPE id){m_id = id;}
protected:
  TYPE m_id;
  virtual void Update(void) = 0;

  virtual void Render(void) = 0;

 public:
  void GetTypeOf(void)const{return m_id;}
};

 class Component : Object
 {
  enum COMPONENT_TYPE
 {
  COLLIDER,
  RENDERER,
  ETC,,,,
 };
   Component() : Object (COMPONENT){/**/}
   virtual void Update(void){return;}
   virtual void Render(void){return;}
   };

     class BoxCollider : Component
     {
      BoxCollider(void) : Component(BOXCOLLIDER){/**/}
      void Update(void)
      {
        //to do
         }
       void Render(void)
      {
          //to do
         }
     };

那么您可以简单地拥有 Object* 或 Component* 的数据结构 你可以通过这种方式迭代:

   std::vector<Component*>::iterator components = ComponentVector.begin();
   for(;components != ComponentVector.end() ; ++components)
   {
      *(component)->Update();
       *(component)->Render();
        std::cout << "id" << *component->getTypeOf() << std::endl; 
   }

【讨论】:

    【解决方案2】:

    Object 类继承自它的所有Components,这意味着它实际上它的所有组件。
    您可以使用此信息来设计您的 update 方法。
    举个例子:

    #include <cassert>
    
    struct Game { };
    
    struct Physics {
        int position{0};
    
        Physics(Game *) { }
        void update(void *) { }
    };
    
    struct Drawable {
        Drawable(Game *) { }
    
        void update(Physics *physics) {
            physics->position = 42;
        }
    };
    
    template<class ... Components>
    class Object: public Components... {
    public:
        Object(Game* game) : Components(game)... { }
    
        void update() {
            int a[] = { (Components::update(this), 0)... };
        }
    };
    
    int main() {
        Game game;
        Object<Physics, Drawable> object{&game};
        assert(object.position == 0);
        object.update();
        assert(object.position == 42);
    }
    

    在这里您可以看到Drawable 在其update 方法被调用时收到Physics
    这种解决方案的缺点是:

    • 组件的update 方法必须获取指针参数,即使它们不需要引用任何其他组件。
    • 如果存在需要引用多个组件的组件,您必须获取两个或多个指针作为 update 方法的参数,或者强制转换 void *

    【讨论】:

      猜你喜欢
      • 2019-07-23
      • 1970-01-01
      • 2010-09-27
      • 2020-03-29
      • 1970-01-01
      • 2010-10-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多