如何高效使用dynamic_cast?

How to use dynamic_cast efficiently?

有一个抽象class Entity,其他class像PlayerEnemy都是从它继承的。当游戏检测到实体之间发生碰撞时,将调用以下方法:

    void handleCollision(Entity* ent1, Entity* ent2) {
        if (dynamic_cast<Player*>(ent1) || dynamic_cast<Player*>(ent2) &&
            dynamic_cast<Enemy*>(ent1) || dynamic_cast<Enemy*>(ent2)) {
            //player <-> enemy collision
        }
        else if (dynamic_cast<Player*>(ent1) || dynamic_cast<Player*>(ent2) &&
                 dynamic_cast<Projectile*>(ent1) || dynamic_cast<Projectile*>(ent2)) {
            //player <-> projectile collision
        }
        else if () {
            //...
        }
        else if() {
            //...
        }
    }

每个实体在与另一个实体碰撞时都有独特的行为,这取决于实体的类型(玩家、敌人等),这就是为什么我需要检查实体之间所有可能的组合,如上所示。但我不喜欢它创建一个巨大的 else if 链,其中每个实体都被多次检查。还有其他方法吗?

使用Entityclass中定义的虚函数来唯一标识派生的class是Player还是Enemy 。这也是避免任何运行时错误的好习惯。

 enum EntityType { Entity, Player, Enemy}

在实体中class定义这样一个虚函数,

virtual EntityType getType (return Entity;)

并相应地在两个 class 中覆盖该函数。

试图扩展 Ben Voigt 关于 多个虚拟调度 的评论,大致如下:

void handleCollision(Entity* ent1, Entity* ent2)
{
  ent1->collide_with(ent2);
}

其中:

class Entity
{
 public:
  virtual void collide_with(Entity*) = 0; // Dispatcher

  virtual void handle_collision_with(Entity*) {}
  virtual void handle_collision_with(class Player*) {}
  virtual void handle_collision_with(class Enemy*) {}
  virtual void handle_collision_with(class Projectile*) {}
};


class Player : public Entity
{
public:
  virtual void collide_with(Entity* other) override
   {
    other->handle_collision_with(this);
   }

  virtual void handle_collision_with(Entity* other) override
   {
    // Unhandled entity
   }

  virtual void handle_collision_with(Player* other) override
   {
    // Handle collision player-player
   }

  virtual void handle_collision_with(Projectile* projectile) override
   {
    // Handle collision player-projectile
   }
};

class Enemy : public Entity
{
public:
  virtual void collide_with(Entity* other) override
   {
    other->handle_collision_with(this);
   }

  virtual void handle_collision_with(Enemy* other) override
   {
    // Handle collision enemy-enemy
   }

  virtual void handle_collision_with(Player* player) override
   {
    // Handle collision enemy-player
   }

  virtual void handle_collision_with(Projectile* projectile) override
   {
    // Handle collision enemy-projectile
   }
};

class Projectile : public Entity
{...}

来源:a-polyglots-guide-to-multiple-dispatch