2016-02-16 34 views
4

我正在开发一个非常小而简单的C++游戏引擎。我有一个生物类和一个武器类。生物需要知道它有什么武器,每个武器需要知道拥有它的生物。我希望武器知道生物具有何种功能的主要原因是为了防止它破坏它自己的生物(当武器攻击时,它将检测它碰撞并杀死它们的所有生物,除了拥有武器的生物)。两个需要相互引用的对象。馊主意?

这里是(简化)生物类的样子:

class Creature { 
    private: 
    Weapon* weapon_; 
    public: 
    void SetWeapon(Weapon* w){ 
     // do some other stuff (e.g. remove Weapon from any other Creatures) 
     weapon_ = w; 
     w->creature_ = this; 
    } 
} 

这里是(简化)的武器类的样子:

class Weapon{ 
    friend class Creature; // Creature needs access to creature_ pointer 
    private: 
    creature_; 
} 

正如你所看到的,我已经生物武器的朋友类,以便Creature的setWeapon()方法可以适当地设置私人生物_指针。

我的具体问题:

  1. 我听说两个对象引用对方是糟糕的设计。但就我而言,我怎么会不这样做呢?我真的“感觉到”每个生物都应该知道它有什么武器,每个武器都应该知道生物具有什么(以便它不会伤害生物)。有没有什么方法可以实现我想要的,而不需要让这两个类互相引用?我在Map/Entity,Inventory/Item等游戏引擎中一次又一次地遇到了这个SAME问题。似乎每当我有一个“Container”类和一个“Item”类时,这个引用问题就会重新出现。我想把这个项目加入到其中一个类中,但我希望两个类彼此知道(即我想让生物知道它的武器和武器知道它的生物)。没有任何方法可以实现这一点,而不需要两个项目相互引用?

  2. 这种设计有时是必需的吗?还是有一种通用的方式来总是避免它,但实现相同类型的功能?

  3. 如果这种设计对于实现这种功能来说确实是必要的,那么使用朋友类是否有正确的方法来处理它?

非常感谢你提前。我非常有兴趣学习如果有一种方法可以实现这种类型的功能,而不需要对象彼此引用。

+1

你有没有考虑让这个生物进攻而不是武器?然后,你可以拥有攻击()方法,因为该生物拥有武器并且该生物知道自己,所以该武器和生物都知道。 – Knox

+0

@Knox我的确在想这个,但是我希望攻击行为在于武器而不是生物。当一个生物被告知攻击()时,它应该简单地委托给weapon_.attack()。这将允许生物动态交换武器。 – MeLikeyCode

+0

然后或许让生物的attack()方法调用武器的_attack(实体),这样你可以为武器范围内的每个实体(不包括它本身)调用_attack()。 – Knox

回答

1

这样那样的问题时有发生的时间,并通过以下方法得到解决:

class Creature { 
public: 
    void SetWeapon(Weapon* w) { 
     weapon_ = w; 
     weapon_->SetCreature(this); 
    } 
private: 
    Weapon* weapon_; 
}; 

class Weapon { 
public: 
    void SetCreature(Creature* _creature) { 
     m_owner = _creature; 
    } 
private: 
    Creature* m_owner; 
}; 

关于您的广泛的问题 - 如果你在同一个项目相当往往会碰到这样那样的问题,我建议您重新考虑您的设计解决方案。例如,你关于武器知道它的生物的主张是违反直觉的,并且感觉不正确。所以从这个假设开始,我相信你最终会得到更好的设计,在那里你的武器不会知道他们的所有者(比如在现实生活中)。

+0

伟大的解决方案,但问题是,现在我无法改变武器属于哪个生物。我可能应该提到,在我的问题中,我会继续并更新它。谢谢! – MeLikeyCode

+0

@MeLikeyCode如果你将'Creature&_owner'改成'Creature * _owner',你会得到的# –

+0

@MeLikeyCode更新了我的答案 –

0
  1. 您没有听错。以这种方式使用引用对象并不是一种好的编程习惯,但是再次使用goto也被一些人认为是不好的方法。有关替代方案,请参阅下文

  2. 这个设计可以使用,因为有时我们还需要使用goto循环。很多人不喜欢这种方式。

替代解决方案: 根据你需要我可以建议的替代方法是什么希望这有助于。您可以创建struct以容纳玩家对象和武器对象,而不是在其各自的课程中为对方提供参考。这样,根据需要操作和更改会更容易。即玩家可以拥有很多武器(在这种情况下,你可以在struct中创建一个阵列)。每个玩家都会有一个与它相关的武器实例。

+0

有趣的解决方案。不过我也有一个Map类。将Creatures添加到地图非常直观,但是将CreatureStruct添加到地图对于我的游戏引擎用户来说会感觉很尴尬。尽管如此,我很高兴你提出了这个问题,但我没有立即想到这一点。谢谢! – MeLikeyCode

0

让对象来回引用是很常见的。一个常见的例子是一个指向父代的指针。你的理念完全合理。只要确保你有你的析构函数,以便对象指针被清除。

~Weapon()中,清除Creature指向武器的指针,反之亦然。

+0

啊,谢谢你的回答。事实上,这是常见的和合理的,使我感觉好多了。谢谢! – MeLikeyCode