派生 class of b2Body 或 class 包含 b2Body 对象?

Derived class of b2Body or class containing a b2Body object?

我目前有一个 class 'WorldObject',其中包含一个指向其 b2Body 的指针,以及几个方法和变量。

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

处理这类事情的一般方法是什么?要始终创建 class 中最重要对象的派生 class,还是只创建一个新对象并使所有内容都具有属性?

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

谢谢。

没有最好的办法。这完全取决于上下文:

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

  • 使 WorldObject 派生自 b2Body 实现继承,并且仅当 WorldObjectb2Body 时才执行。这意味着原则上你可以用 WorldObject object 做任何你可以用 b2Boby 做的事情(甚至更多)。

经验法则是 preferring composition over inheritance。除非你真的有明显的遗传。

在你的例子中,b2Body 是刚性的 body。现在问你一个问题:你的 object 是 body 吗?或者你的 object 有 body 吗?

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

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

另请注意,您通常会创建一个调用 b2World::CreateBody() 和 returns 一个 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(...));
    }
};

您一定更喜欢组合而不是继承。组成避免fragile base class problem.

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

  • Subclasses 依赖于它们的 superclasses,它可以被改变,因此 subclasses

    中的功能被破坏
  • 使用组合和转发而不是继承,特别是如果存在实现包装器的适当接口 class。

  • 当class设计为继承时使用继承

我建议您阅读 Joshua bloch 的 "Effective Java" 一书的第 16 "favor composition over inheritance" 条