在这种情况下如何避免 dynamic_cast ?

How to avoid dynamic_cast in this case?

我的程序中有 3 个 classes:

class GameObject{

    private:
        std::pair<int, int> position;
}

class World{

    private:
        std::vector<GameObject*> gameObjects;
        int gravity;

}

class MovingObject : public GameObject{

    private:
        int velocity;
        bool isSensitiveToGravity;
        unsigned mass;
}

我在世界 class 中使用 GameObject* 的矢量,因为我想把游戏中的每个对象都放在那里,有些对象 不是 MovingObject 个实例。

但我看到了一个问题:在游戏过程中,我需要循环 world.gameObjects 以检查物体是否对重力敏感,如果是的话,将其向下拖动,但是如何我应该这样做吗?

我的第一个想法是在 GameObject class 中添加一个纯虚方法,该方法将在 MovingObject class 和 return 中实现一个物体是否对重力敏感,但这不是一个奇怪的设计吗?

另一个想法当然是在每个对象上使用 dynamic_cast,检查 MovingObject 的 (sub)class,然后检查 isSensitiveToGravity 字段, 但我读了很多应该避免 dynamic_cast 的文章,它几乎总是糟糕设计的标志,那么我的错误在哪里?

谢谢!

当您考虑 OOP 中的功能时,您应该考虑接口而不是数据结构。正是这种情况,因此您应该创建一个带有函数 interactWithGravity 的接口并使用它。如果这是一个不与重力相互作用的物体,则什么都不做。

为了强调为什么这是正确的解决方案,让我们考虑另一种选择,使用一个参数来确定它是否可以通过重力移动。这有以下缺点:

  1. 如果你有更多的参数影响某些对象如何与重力相互作用意味着添加另一个 属性 到通用结构(尽管它只与某些相关)。
  2. 前面的示例还表明您需要扩展遍历对象的 main 函数中的用例,并使代码更复杂且更难扩展。
  3. 也许您会发现在极坐标中进行“重力计算”会更容易。这意味着更改不同对象中的所有计算和坐标。

如果您需要进行一些优化,则持有不同的列表可能是合理的,否则由于类似的原因,它的可重用性和可消耗性会降低。

关于其他概念(如 ISP)的列表不胜枚举,但您已经了解了大致的概念。