我在一个头文件中定义了一个名称空间,并在另一个头文件中使用,但找不到它。具体来说,在名为“combat / Targetable.hpp”的文件中找不到名为“players / Players.hpp”中定义并在名为“players / Ownable.hpp”的文件中使用的名为“players”的名称空间
错误是
...\source\combat\Targetable.hpp(7): 'players' : is not a class or namespace name
...\source\combat\Targetable.hpp(7): 'Ownable' : base class undefined
显然这是一些我不理解的语法。我花了一些时间来简化代码,所以它看起来很傻,但请耐心等待。
// source/players/Players.hpp:
#ifndef PLAYERS_HPP
#define PLAYERS_HPP
#include "../Headers.hpp"
namespace players {
class Player{
// this class compiles fine.
// There used to be a "Players.cpp" but it's been simplified away
public:
int getID(){ return 0; }
int getTeam(){ return 0; }
string getName(){ return ""; }
Vec3 getColor(){ return Vec3(0.0,0.0,0.0); }
};
}
#endif
玩家/ Ownable.hpp,与Player.hpp位于同一个文件夹中并且编译良好:
// source/players/Ownable.hpp:
#ifndef OWNABLE_HPP
#define OWNABLE_HPP
#include "Players.hpp"
namespace players {
class Ownable;
typedef boost::shared_ptr<Ownable> OwnablePTR;
typedef boost::weak_ptr<Ownable> OwnableWPTR;
class Ownable {
public:
Ownable(){}
Ownable(int playerID) : playerID(playerID){}
bool isAlliedWith(OwnablePTR other){ return false; }
private:
int playerID;
};
}
#endif
这是有趣的开始。我在“source / combat / Targetable.hpp”中有一个文件,该文件与其他两个文件位于不同的目录中。但是,文件本身似乎包括罚款:
// source/combat/Targetable.hpp:
#ifndef TARGETABLE_HPP
#define TARGETABLE_HPP
#include "../players/Ownable.hpp"
namespace combat{
class Targetable : public players::Ownable { // ERROR
public:
Targetable(int playerID){}
//Targetable(players::Player player);
virtual Vec2 getPosition(){
return Vec2();
}
virtual Vec2 getVelocity(){
return Vec2();
}
};
}
#endif
我真的希望这是一些我不知道的愚蠢语法。我甚至试过
using players::Ownable;
但是A)污染了包含这个文件的文件,B)没有修复任何东西。有什么帮助吗?
编辑:GManNickG得到它,它是Headers.hpp文件中的循环包含。谢谢!
答案 0 :(得分:3)
你有一个循环包含。
首先考虑包含警卫的目的:
// a.hpp
#ifndef A_HPP
#define A_HPP
// stuff
#endif
// b.hpp
#ifndef B_HPP
#define B_HPP
#include "a.hpp"
// stuff
#endif
// c.hpp
#ifndef C_HPP
#define C_HPP
#include "a.hpp"
#include "b.hpp"
// stuff
#endif
// x.cpp
#include "c.hpp"
包含c.hpp
最终会包含a.hpp
两次。第一次,守卫没有被定义,一切都很好,第二次守卫阻止重新定义。这就是我们想要的。
但是当你有一个循环时,这不起作用。 (它会阻止它,这很好,但它确实“太好了”,因为防护是在测试后立即定义的,这意味着标题的内容实际上还没有被处理过)。请考虑一下:
// a.hpp
#ifndef A_HPP
#define A_HPP
#include "c.hpp"
// stuff
#endif
// b.hpp
#ifndef B_HPP
#define B_HPP
#include "a.hpp"
// stuff
#endif
// c.hpp
#ifndef C_HPP
#define C_HPP
#include "b.hpp"
// stuff
#endif
// x.cpp
#include "c.hpp"
这与你的相似。 x.cpp
包含c.hpp
,这是第一次被包含在内,因此它定义了C_HPP
。然后c.hpp
包含b.hpp
,其中包含a.hpp
。然后a.hpp
包含c.hpp
,而发现C_HPP
已经定义,因此包含不执行任何操作。
假设a.hpp
仍然设法编译(即实际上不需要c.hpp
),那么a.hpp
完成,然后b.hpp
完成,然后{{1}最后在返回c.hpp
之前实际定义了它的内容。
解决方案是尽量减少您包含的标头数量。使用前向声明,最重要的是:不要使用“包含所有内容”标题!这些可怕。而且我怀疑那是x.cpp
。
答案 1 :(得分:1)
class Targetable : public ::players::Ownable { . . .
怎么样?
请注意::
之前的全局命名空间资格players
。