所以我有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方法。
答案 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文件中,首先包含您自己的头文件;然后包含任何其他标头,用于需要其声明的类(如果您定义的方法按值实例化这些其他类的实例,或者调用这些其他类的方法,则需要它们。)
有时您可能希望在头文件中按值(而不是通过指针或引用)引用第二个类;没关系,但是如果你这样做,那么你就是一个循环依赖的中途。如果确实以循环依赖关系结束,那么您需要更改它,以便至少有一个类(如果不是两个)仅通过指针或引用而不是通过值引用另一个类。