如何解决这个C++多重继承类似的问题

How to solve this C++ multiple inheritance similar issue

本文关键字:多重继承 C++ 问题 何解决 解决      更新时间:2023-10-16

我想知道避免以下问题的推荐方法是什么。

我有一个类 rigidBody3D,它有一个指向另一个刚性 Body 结构的指针,还有一个继承 rigidBody3D 的类 box3D。

class rigidBody3D {
public:
    void setPosition(float x, float y, float z);
    rigidBody* rb;
};
class box3D : public rigidBody3D {
public:
    box3D(float w float h, float l);
    ..other box functions..
};

然后,我有了使用这些 3D 类的 2D 类。

class rigidBody2D {
public:
    rigidBody2D();
    void setPosition(float x, float y);
    rigidBody3D body;
};
class box2D : public rigidBody2D {
public:
    box2D(float w, float h);
    box3D box;
};

例如,rigidBody2D 的 setPosition 调用其 rigidBody3D 的 3D setPosition。

void rigidBody2D::setPosition(float x, float y)
{
    body.setPosition(x,y,0);
}

问题:

按原样,创建 box2D 对象会创建两个刚性 Body 指针。一个是因为box2D继承了刚性Body2D,它有一个刚性Body3D。另一个是因为 box2D 有一个继承 rigidBody3D 的 box3D 对象。

我只想要一个刚性身体指针。我还希望能够为 2D 类调用 2D setPosition,如 box2D,但也调用它们的 3D 特定函数,如 box2D 调用 box3D。

溶液:

我使用虚拟继承来解决问题,并且还继承了 3D 类而不是它们的对象。

class rigidBody3D {
public:
    void setPosition(float x, float y, float z);
    rigidBody* rb;
};
class box3D : public virtual rigidBody3D {
public:
    box3D(float w float h, float l);
    ..other box functions..
};
class rigidBody2D : private virtual rigidBody3D {
public:
    rigidBody2D();
    void setPosition(float x, float y);
};
class box2D : public rigidBody2D, private box3D  {
public:
    box2D(float w, float h);
};
void rigidBody2D::setPosition(float x, float y)
{
    rigidBody3D::setPosition(x,y,0);
}

您的评论:

我想要 (...) 2D 对象,它们是以 2D 绘制并具有 z 的 3D 对象 组件设置为 0

强烈建议rigidBody2DrigidBody3Dbox2Dbox3D。因此,选择继承而不是组合似乎是很自然的:

备选方案1:简单继承

在这里,我们将考虑所有这些2D和3D对象的根源是刚性Body2D。一个问题仍然存在:box2D更像是一种box3D还是更像是一个rididBody2D?

class rigidBody2D : public rigidBody3D {
public:
    rigidBody2D();
    void setPosition(float x, float y);
    // no body anymore:  it's inherited from rigidBody3D 
};
class box2D : public box3D {  // is it more like a box3d or more like a rigiBbody2D ? You decide ! 
public:
    box2D(float w, float h);
    // no box anymore:  it's inherited from box3D 
};
box2D::box2D (float w, float h) : box3D (w, h, 0) { /*...*/ }  // how to create a box2D as a special case of box3D
void rigidBody2D::setPosition(float x, float y)  // call the setpos of the parent.  
{
    rigidBody3D::setPosition(x, y, 0);  // call parent's setpos
}

所有 therse 对象都继承自 rigidBody3D,然后有一个指向rigidBody的指针。

另一个问题是,一个rigidBody3D是否不应该自己继承rigidBody,或者是否有强有力的论据反对(例如:如果两者的寿命不同)。

备选方案2:多重继承

这是关于box2D的设计。 它是否更像是一个 box3D,具有相同类型的成员函数,但比 box3D 多,但考虑到第三维为 0? 还是更像是一个刚性的Body2D,因为它应该拥有并使用这个对象提供的所有成员函数?

如果您可以轻松决定,请返回备选方案 1。

如果你不能决定,因为它是两者兼而有之,那么你可以考虑多重继承:

class box2D : public box3D, public rigidBody2D {   
public:
    box2D(float w, float h);
    // no box anymore:  it's inherited from box3D 
};

你将继承成员(两者的函数和数据)。 豪威尔多重继承并不容易。 你在这里有 2 个刚性身体指针:那些从盒子继承的,以及那些从身体继承的。

在您的

情况下,可以通过使刚性Body3D的继承虚拟来解决:

class rigidBody2D : public virtual rigidBody3D { ... };
class box3D : public virtual rigidBody3D { ... };

在这种情况下,如果一个对象继承了多个时间刚性 Body3D,则只会创建一个这样的子对象。

在我看来

,2D 和 3D 对象仅通过它们是以刚体*实现的事实相关联。对于这两个概念,setPosition的语义是不同的。

另一种说法是,2d身体不是一种3d身体,它是一个不同的概念,所以它们之间似乎不应该有继承关系。

所以我会从这些思路开始思考:

struct rigid_body_3d_concept {
  virtual ~rigid_body_3d_concept();
  void set_position(double x, double y, double z) {
    _impl->really_set_the_position(x, y, z);
  }
private:
  rigidbody* _impl;
};
struct rigid_body_2d_concept {
  virtual ~rigid_body_2d_concept();
  void set_position(double x, double y) {
    _impl->really_set_the_position(x, y, 0);
  }
private:
  rigidbody* _impl;
};
struct box3d 
: public rigid_body_3d_concept 
{
    box3d(double w, double h, double l);
};
struct box2d 
: public rigid_body_2d_concept 
{
    box2d(double w, double h);
};