【问题标题】:Derived class of b2Body or class containing a b2Body object?b2Body 的派生类或包含 b2Body 对象的类?
【发布时间】:2016-04-04 06:26:38
【问题描述】:

我目前有一个“WorldObject”类,它包含一个指向其 b2Body 的指针,以及几个方法和变量。

但是让 WorldObject 成为 b2Body 的派生类不是更聪明吗?

处理这类事情的一般方法是什么?总是为类中最重要的对象创建一个派生类,还是只创建一个新的并让所有东西都具有属性?

这些可能性的优缺点是什么?

谢谢。

【问题讨论】:

    标签: c++ box2d


    【解决方案1】:

    没有最好的方法。这一切都取决于上下文:

    • 拥有指向b2Body 的指针实现了组合关系,即WorldObject 具有b2Body

    • 使WorldObject 派生自b2Body 实现继承,并且仅当WorldObjectb2Body 时才应这样做。这意味着原则上你可以用WorldObject 对象做你可以用b2Boby 做的所有事情(以及更多)。

    经验法则是选择preferring composition over inheritance。除非你真的有明显的继承。

    在您的情况下,b2Body 是刚体。现在问你一个问题:你的对象是一个身体吗?或者你的对象有一个身体?

    更实用:这种设计的优点是它把Box2D引擎的选择封装在你的WorldObject中。如果稍后您使用另一个 API 将您的软件移植到另一个物理引擎,这可以让您更好地控制影响。如果您改用继承,则底层引擎 API 将显着影响您自己的软件的设计,并且有一天很难迁移到另一个引擎。

    【讨论】:

      【解决方案2】:

      通常最好进行组合而不是过度使用继承。

      另请注意,您通常会创建一个调用 b2World::CreateBody() 的主体,并返回一个 b2Body*,并且无法进行继承。

      为了避免内部b2Body* 的生命周期问题,您可以使用智能指针。我使用这个定义:

      class BodyDeleter
      {
      public:
          BodyDeleter()
              :m_world(NULL)
          {}
          BodyDeleter(b2World *world)
              :m_world(world)
          {}
          void operator()(b2Body *body)
          {
              if (m_world)
                  m_world->DestroyBody(body);
          }
      private:
          b2World *m_world;
      };
      
      typedef std::unique_ptr<b2Body, BodyDeleter> b2BodyPtr;
      

      那么,在我的WorldObject

      class WorldObject
      {
      protected:
          WorldObject(b2World *world)
          :m_body(NULL, m_world)
          {}
         b2BodyPtr m_body;
      };
      

      然后,在WorldObject 的实际子类中:

      class SpaceShip : public WorldObject
      {
      public:
          SpaceShip(b2World *world)
          :WorldObject(world)
          {
              //initialize bodydef and whatever
              m_body.reset(world->CreateBody(...));
          }
      };
      

      【讨论】:

        【解决方案3】:

        您必须更喜欢组合而不是继承。组合避免fragile base class problem

        • 与方法调用不同,继承违反封装

        • 子类依赖于它们的超类,这些超类可能会被更改,从而破坏子类中的功能

        • 使用组合和转发而不是继承,尤其是在存在实现包装类的适当接口时。

        • 在为继承设计类时使用继承

        我建议你阅读 Joshua bloch 的“Effective Java”一书的第 16 条“偏好组合优于继承”

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多