例如一个带有三个类玩家,机器人和游戏的小型计算机游戏
玩家有一个方法可以检查玩家是否与机器人发生碰撞
// Player.h
#include Game.h
#include Bot.h
class Player {
private:
bool collision(Game g) {
for (Bot bot: g.bots)
...
}
};
Bot.h(保持简单,因为它有一些其他属性,如实际位置和目前为止)
// Bot.h
class Bot {
public:
Bot()
};
Gameclass处理Gameloop和Bot of Bots
//Game.h
#include Bot.h
#include Player.h
class Game {
public:
Player player:
std::vector<Bot> bots
void loop() { player.collision() }
};
所以这里我们遇到的问题是Game.h包含Player.h,反之亦然。
我该如何解决这个问题?
答案 0 :(得分:3)
虽然这里的其他答案肯定在技术上是正确的,但每当我遇到这样的情况时,我都会将其视为指出我设计中存在的潜在缺陷。你所拥有的是循环依赖,如下所示:
这不仅仅是您实现的问题,它意味着类之间存在太多coupling,或者相反,信息隐藏太少。这意味着您无法独立于Player
设计Game
,例如。
因此,如果可能的话,我更喜欢这样的情况,其中Game
作为控制器委托给其他类。
执行此操作的一种方法是Game
在Player
需要时将collision
传递给自己的属性。
例如,让bots
采用bool collision(const std::vector<Bot&> bots) {
// note pass objects by const ref is usu preferred in C++ to pass by value
for (Bot bot: g.bots)
...
}
参数而不是“游戏
{{1}}
(注意,在更复杂的方法中,它可以将接口,即抽象基类传递给自身)。
如果一切都失败了,你可以回去使用前瞻性声明。
答案 1 :(得分:2)
在这种情况下,最简单的方法是转发声明,并将一些代码从头文件移动到源文件。
喜欢这个
Player.h
#include "Bot.h"
class Game; // forward declaration
class Player {
private:
bool collision(Game g);
};
Player.cpp
#include "Player.h"
#include "Game.h"
bool Player::collision(Game g) {
for (Bot bot: g.bots)
...
}
前向声明告诉编译器Game
是类的名称,但没有别的。因此必须将Player::collision
方法移动到Player.cpp文件中,其中可以使用Game的完整定义。
答案 2 :(得分:1)
我认为你不能这样做,因为如果A包含B,而B包含A,它将是无限大小。事实上,您可以使用前向声明创建两个存储指针的类,以便两个类知道彼此的存在
答案 3 :(得分:1)