c++ b2Body的派生类还是包含b2Body对象的类?

m1m5dgzv  于 2023-01-28  发布在  其他
关注(0)|答案(3)|浏览(105)

我目前有一个类'WorldObject',它包含一个指向其b2Body的指针,以及几个方法和变量。
但是,使WorldObject成为b2Body的派生类不是更聪明吗?
对于这类事情,一般的方法是什么?,总是创建一个类中最重要的对象的派生类,还是只创建一个新的,并使所有的对象都具有属性?
这些可能性的利弊是什么?
谢谢你。

fcg9iug3

fcg9iug31#

没有最好的办法,这完全取决于具体情况:

  • 具有指向b2Body的指针实现了组合关系,即WorldObject具有b2Body
  • 使WorldObjectb2Body派生实现了继承,并且只有当WorldObjectb2Body时才应该这样做。这意味着原则上,你可以用WorldObject对象做你可以用b2Boby做的任何事情(甚至更多)。

经验法则是选择preferring composition over inheritance,除非你真的有明显的继承。
在您的示例中,b2Body是刚体。现在问您一个问题:你的对象是一个身体吗?或者你的对象是身体吗?
更实用:这种设计的优势在于它将Box2D引擎的选择封装在WorldObject中。如果以后您使用另一个API将软件移植到另一个物理引擎,这将使您能够更好地控制影响。如果您使用继承,底层引擎API将显著影响您自己软件的设计,并使其在某一天很难移植到另一个引擎。

gzjq41n4

gzjq41n42#

通常最好进行组合,而不要过度使用继承。
还要注意,通常创建一个调用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(...));
    }
};
l2osamch

l2osamch3#

你一定更喜欢复合而不是继承。复合避免了fragile base class problem

  • 与方法调用不同,继承违反封装
  • 子类依赖于它们的超类,而超类可以更改,从而破坏子类中的功能
  • 使用组合和转发代替继承,特别是在存在实现 Package 类的适当接口时。
  • 当类设计为继承时使用继承

我建议您阅读约书亚Bloch的《有效的Java》一书中的第16条“更喜欢组合而不是继承

相关问题