如何解决这个 C++ 多重继承类似的问题
Posted
技术标签:
【中文标题】如何解决这个 C++ 多重继承类似的问题【英文标题】:How to solve this C++ multiple inheritance similar issue 【发布时间】:2014-11-27 18:10:05 【问题描述】:我想知道避免以下问题的推荐方法是什么。
我有一个rigidBody3D 类,它有一个指向另一个rigidBody 结构的指针,还有一个继承了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 对象会创建两个刚体指针。一个是因为 box2D 继承了具有rigidBody3D 的rigidBody2D。另一个是因为 box2D 有一个 box3D 对象,它继承了rigidBody3D。
我只想要一个刚体指针。我还希望能够为 box2D 等 2D 类调用 2D setPosition,但也可以调用它们的 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 身体保持 3d 身体来实现什么?你想模拟什么样的真实世界情况? 为什么不从3D物体继承2D物体,并将z
坐标设置为0呢?您可能还应该更多地考虑您的设计,以及基类中应该包含什么。
我有一个指针指向的原始刚体的界面全是 3D。我想让我的 3D 图层尽可能靠近指针。我的 2D 类是为了简化我以后添加 2D 对象的任务,这些对象是以 2D 绘制的 3D 对象,并且它们的 z 分量设置为 0。
重新设计是我想做的。知道我想要一个 3D 后端和一个简化的 2D 界面,您有什么建议吗?
这是一种可能的解决方案。另一种方法是将层次结构模板化为维度数量,以便您拥有object<2>
、object<3>
等。
【参考方案1】:
您的评论:
我想要 (...) 2D 对象,它们是 3D 对象,以 2D 形式绘制并具有其 z 组件设置为 0
强烈建议rigidBody2D
是一个 rigidBody3D
,而box2D
是一个强>box3D
。因此,更喜欢继承而不是组合似乎很自然:
替代方案 1:简单继承
这里我们将考虑所有这些 2D 和 3D 对象的根是rigidBody2D。 一个问题仍然存在: 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
所有其他对象都从rigidBody3D
继承,然后有一个指向rigidBody
的指针。
实际上,另一个问题是要知道rigidBody3D
自己是否不应该从rigidBody
继承,或者是否有强烈的反对意见(例如:如果两者的寿命不同)。
备选方案 2:多重继承
这里是关于box2D的设计。它是否更像一个 box3D,具有相同类型的成员函数,但比 box3D,但考虑到第三维是 0 ?或者它更像是一个rigidBody2D,因为它应该拥有并使用这个对象提供的所有成员函数?
如果您可以轻松决定,请返回备选方案 1。
如果你不能决定,因为它有点两者兼而有之,那么你可以考虑多重继承:
class box2D : public box3D, public rigidBody2D
public:
box2D(float w, float h);
// no box anymore: it's inherited from box3D
;
那么您将继承成员(两者的函数和数据)。然而多重继承并不容易。您将在这里有 2 个刚体指针:从盒子继承的指针和从主体继承的指针。
在您的情况下,可以通过将rigidBody3D 虚拟继承来解决此问题:
class rigidBody2D : public virtual rigidBody3D ... ;
class box3D : public virtual rigidBody3D ... ;
在这种情况下,如果一个对象继承了多次rigidBody3D,那么只会创建一个这样的子对象。
【讨论】:
非常感谢!我实际上使用了它们的组合。【参考方案2】:在我看来,2d 和 3d 对象的相关性仅在于它们是根据刚体* 实现的。 setPosition
的语义对于这两个概念是不同的。
另一种说法是,2d body 不是 一种 3d body,它是一个不同的概念,所以它们之间似乎不应该有继承关系。
所以我会从这些思路开始:
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);
;
【讨论】:
以上是关于如何解决这个 C++ 多重继承类似的问题的主要内容,如果未能解决你的问题,请参考以下文章