奇怪的循环依赖问题

时间:2009-10-21 01:03:07

标签: c++

所以我有2个类,Bullet和Ship,它们相互依赖,因此循环包含。由于我将Ship的界面#include包含在Bullet的界面中,显而易见的决定是将子弹声明转发给Ship。

然而,当我第一次尝试这个时,我仍然遇到编译器错误。我读了一下前向声明并意识到我正在使用Ship的一个方法构建一个Bullet,并且Bullet的默认构造函数是成员初始化的,这(并且我可能是错的)不起作用,因为前向类声明不允许Ship查看界面中的定义(即成员初始化)。

所以我决定放弃成员init并在Bullet的实现文件中定义构造函数,但是我仍然遇到循环依赖的相同问题。

特别是invalid use of undefined type struct Bullet

我可以将Bullet和Ship的界面放在同一个文件中,但这是最后的手段。对此问题的任何帮助表示赞赏。感谢。

以下是发生错误的位置:

case SDLK_UP: // Fire
{
    Bullet(*this) fired_bullet; // Create bullet. Line where error occurs.
    fired_bullet.Move(); // Move bullet
    break;
}

Bullet的默认构造函数接受发射子弹的Ship的参数,该代码采用Ship方法。

4 个答案:

答案 0 :(得分:5)

你想:

Bullet fired_bullet(*this);

但你的耦合很紧张。什么子弹需要从船上发货,什么船需要从子弹?

我认为子弹需要知道它来自哪艘船,所以敌人的子弹不会伤害敌人,反之亦然。也许你需要一个团队类型?

enum bullet_team
{
    bullet_player,
    bullet_enemy,
}

你的船只和敌人只会告诉子弹他们在哪个团队,而不是强迫子弹跟踪它来自哪里:

关于射击,也许制作一个BulletManager单身人士。告诉经理你要在X位置制作子弹,团队方向Y和属性Z,经理会为你处理。

BulletManager::reference().fire(getPosition(), bullet_player);

答案 1 :(得分:2)

取代:

Bullet(*this) fired_bullet;

使用:

Bullet fired_bullet(*this);

答案 2 :(得分:1)

您必须将标题中的定义移到源文件中,只在标题中留下声明。看起来应该是这样的:

// Ship.h
class Bullet;
class Ship
{
    // Declare stuff, using only pointers/references to Bullet instances
    Ship();
    ...
};

// Bullet.h
class Ship;
class Bullet
{
    // Declare stuff, using only pointers/references to Ship instances
    Bullet(const Ship & ship);
    ...
};

// Ship.cpp
#include "Bullet.h"
#include "Ship.h"

// Ship definitions
Ship::Ship()
{
    ...
}
...

// Bullet.cpp
#include "Bullet.h"
#include "Ship.h"

// Bullet definitions
Bullet::Bullet(const Ship & ship)
{
    ...
}
...

最后,实例化Bullet的语法是错误的。你应该像这样实例化它:

Bullet fired_bullet(*this);

答案 3 :(得分:0)

一种方法如下。

<强> Bullet.h

class Ship; //forward declaration
class Bullet
{
  //declaration of Bullet
  //may use Ship references and Ship pointers
};

<强> Bullet.cpp

#include "Bullet.h"
#include "Ship.h"
//definitions of Bullet methods go here

<强> Ship.h

class Bullet; //forward declaration
class Ship
{
  //declaration of Ship
  //may use Bullet references and Bullet pointers
};

<强> Ship.cpp

#include "Ship.h"
#include "Bullet.h"
//definitions of Ship methods go here

这将始终有效:

  • 在每个头文件中,声明一个类;对其他类使用前向声明(仅名称),并且仅通过引用或指针引用这些类(作为成员方法参数和作为成员实例数据),而不是通过值引用。

  • 在每个CPP文件中,首先包含您自己的头文件;然后包含任何其他标头,用于需要其声明的类(如果您定义的方法按值实例化这些其他类的实例,或者调用这些其他类的方法,则需要它们。)

有时您可能希望在头文件中按值(而不是通过指针或引用)引用第二个类;没关系,但是如果你这样做,那么你就是一个循环依赖的中途。如果确实以循环依赖关系结束,那么您需要更改它,以便至少有一个类(如果不是两个)仅通过指针或引用而不是通过值引用另一个类。