简体   繁体   English

如何有效地使用dynamic_cast?

[英]How to use dynamic_cast efficiently?

There is an abstract class Entity , and other classes like Player and Enemy are inherit from it.有一个抽象的 class Entity ,其他类如PlayerEnemy都继承自它。 When game detects a collision between the entities, the following method is called:当游戏检测到实体之间的碰撞时,会调用以下方法:

    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() {
            //...
        }
    }

Each entity has unique behavior when colliding with another, which depends on the type of entity (Player, Enemy, etc), that's why I need to check every possible combination between entities as shown above.每个实体在与另一个实体发生碰撞时都有独特的行为,这取决于实体的类型(玩家、敌人等),这就是为什么我需要检查实体之间所有可能的组合,如上所示。 But I don't like the fact it creates a huge else if chain, where each entity is checked multiple times.但我不喜欢它创建一个巨大的 else if 链,每个实体都被检查多次的事实。 Is there another way of doing it?还有另一种方法吗?

Trying to expand Ben Voigt's comment about multiple virtual dispatch , something along the lines of:试图扩展 Ben Voigt 关于多个虚拟调度的评论,大致如下:

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

Where:在哪里:

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
{...}

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

Use a virtual function defined in Entity class to uniquely identify the derived class whether Player or Enemy .使用Entity class 中定义的虚拟 function 来唯一标识派生的 class 是Player还是Enemy This will be a good practice to avoid any runtime errors as well.这也是避免任何运行时错误的好习惯。

 enum EntityType { Entity, Player, Enemy}

In the Entity class define a virtual function like this,在实体 class 中定义一个虚拟 function 像这样,

virtual EntityType getType (return Entity;)

and override the function in two classes accordingly.并相应地在两个类中覆盖 function。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM