多重继承,还是其他什么?

时间:2011-12-13 20:43:52

标签: c++ inheritance polymorphism

假设我有以下继承树:

SDLBullet inherits from Bullet inherits from Entity
EnemyBullet inherits form Bullet inherits from Entity

现在我需要一个新类SDLEnemyBullet,它需要在SDLBullet中实现的绘制,以及在EnemyBullet中实现的冲突。我该怎么做?这是使用多重继承来解决的吗?如果没有,请随时编辑我的问题和标题。如果是这样,我将如何实现这样的事情?

下面的一些代码示例:

class Entity {
  bool collision(Entity) = 0;
  void draw() = 0;
}

class Bullet : Entity {
  bool collision(Entity) {/*some implementation*/};
  void draw() {/*draw me*/};
}

class SDLBullet : Bullet {
  void draw() {/*draw me using SDL*/};
}

class EnemyBullet : Bullet {
  bool collision(Entity) {/*if Entity is a fellow enemy, don't collide*/};
}

class SDLEnemyBullet : ????? {
  /*I need SDLBullet::draw() here*/
  /*I need EnemyBullet::collision(Entity) here*/
  /*I certainly do not want EnemyBullet::draw nor SDLBullet::collision here*/
}

非常感谢任何帮助!

(顺便说一下:这是一个学校项目,这样的继承树是向我们建议的。没有人阻止我们做这个不同和更好。这就是为什么我问这个问题。)

4 个答案:

答案 0 :(得分:3)

教科书解决方案涉及多个虚拟继承。

class SDLBullet : public virtual Bullet {
  void draw() {/*draw me using SDL*/};
};

class EnemyBullet : public virtual Bullet {
  bool collision(Entity) {/*if Entity is a fellow enemy, don't collide*/};
};

class SDLEnemyBullet : public SDLBullet, public EnemyBullet {
  // just one Bullet subobject here
};

答案 1 :(得分:2)

通常情况下,使用访问者模式,使用多个调度或使用C ++(没有此功能)完成冲突。

但是

为什么你没有像这样的层次结构呢?

class Entity;

class Bullet : public Entity
{
public:
 virtual draw();
}

class FriendlyBullet : public Bullet
{
public: 
bool collide(EnnemyBullet*);
bool collide(FriendlyBullet*);
}
class EnnemyBullet : public Bullet
{
public:
 bool collide(EnnemyBullet*);
bool collide(FriendlyBullet*);
}

这也可以,并且不需要multidispatch或多继承

答案 2 :(得分:2)

您需要指定逗号分隔的超类列表:

class SDLEnemyBullet : public SDLBullet, public EnemyBullet {
  /*I need SDLBullet::draw() here*/
  /*I need EnemyBullet::collision(Entity) here*/
  /*I certainly do not want EnemyBullet::draw nor SDLBullet::collision here*/
}

看起来你正在制作游戏(引擎)。为了避免像这样的复杂继承结构的需要,有利于组合而不是实体的继承,即有一个实体对象包含用于渲染的单独的“组件”对象等。这样你可以混合和匹配你喜欢的组件而不会爆炸类与超类的所有不同组合。

这是一篇关于这个主题的好文章:http://cowboyprogramming.com/2007/01/05/evolve-your-heirachy/

答案 3 :(得分:1)

<强> Prefer composition over inheritance

你不需要继承来组合那些与此无关的东西。组成游戏逻辑,物理,声音,输入,图形(可能使用继承)的基本对象(实体?),并将那些只包含所述对象数组的GameObject组合起来。

一些漂亮的交叉链接很有用,因为它们都会共享一个Frame或Transform,但是这可以在创建过程中通过迭代所有其他对象并使用dynamic_cast来完成......(如果你不这样做,它会很有用)需要依赖初始化顺序。)

但是真的没有必要用继承来构建它。它不适合您的用例。 (虽然虚拟继承是有用的,但使用继承强制不同的东西变得相同,即使所有东西成为某些东西,而不是由不同的部分组成,这不是一件好事(渲染,伤害,声音等......)。

阅读thisthis了解更多信息,或者只需点击标题即可谷歌。 :)