尽管它是正确的,但找不到命名空间

时间:2021-12-17 00:59:42

I have a namespace defined in one header file and used in another, but it cannot be found. Specifically, a namespace called "players" defined in "players/Players.hpp" and used in a file called "players/Ownable.hpp" cannot be found in a file called "combat/Targetable.hpp"

我在一个头文件中定义了一个名称空间,并在另一个头文件中使用,但找不到它。具体来说,在名为“combat / Targetable.hpp”的文件中找不到在“players / Players.hpp”中定义并在名为“players / Ownable.hpp”的文件中使用的称为“播放器”的命名空间。

The errors are

错误是

...\source\combat\Targetable.hpp(7): 'players' : is not a class or namespace name
...\source\combat\Targetable.hpp(7): 'Ownable' : base class undefined

Obviously it's some syntax thing I don't understand. I've spent some time simplifying the code so it looks silly, but bear with me.

显然这是我不理解的一些语法。我花了一些时间简化代码,所以它看起来很傻,但请耐心等待。

// 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

And players/Ownable.hpp, which is in the same folder as Player.hpp and also compiles fine:

和player / 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

Here's where the fun starts. I have a file at "source/combat/Targetable.hpp", which is in a different directory than the other two. However, the file itself seems to include fine:

这是有趣的开始。我在“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

I'm really hoping this is some silly syntax thing that I'm missing. I've even tried

我真的希望这是一些我错过的愚蠢语法。我甚至试过了

using players::Ownable;

but that A) pollutes the files that include this one, and B) doesn't fix anything. Any help?

但是A)污染了包含这个文件的文件,B)没有修复任何东西。有帮助吗?

EDIT: GManNickG got it, it was a circular include in the Headers.hpp file. Thanks!

编辑:GManNickG得到它,它是Headers.hpp文件中的循环包含。谢谢!

2 个解决方案

#1


3  

You have a circular include.

你有一个循环包括。

First consider the purpose of include guards:

首先考虑包括警卫的目的:

// 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"

The inclusion of c.hpp will end up include a.hpp twice. The first time, the guards are not defined and everything is okay, and the second time the guards prevent redefinitions. This is what we want.

包含c.hpp最终将包括a.hpp两次。第一次,守卫没有定义,一切都很好,第二次守卫阻止重新定义。这就是我们想要的。

This does not work when you have a loop, though. (It will prevent it, which is good, but it does "too well" because the guard is defined right after its tested, which means the contents of the header haven't actually yet been processed). Consider this instead:

但是,当你有一个循环时,这不起作用。 (它会阻止它,这很好,但它确实“太好了”,因为防护是在测试后立即定义的,这意味着标头的内容实际上还没有被处理过)。请考虑一下:

// 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"

Which is similar to what you have. x.cpp includes c.hpp, which is the first time it's been included so it defines C_HPP. Then c.hpp includes b.hpp, which includes a.hpp. Then a.hpp includes c.hpp and finds that C_HPP has already been defined, so the include does nothing.

这和你的相似。 x.cpp包含c.hpp,这是第一次包含它,因此它定义了C_HPP。然后c.hpp包含b.hpp,其中包括a.hpp。然后a.hpp包含c.hpp并发现已经定义了C_HPP,因此include不执行任何操作。

Assuming a.hpp still manages to compile (that is, c.hpp isn't actually needed), then a.hpp finishes, then b.hpp finishes, then c.hpp finally actually defines its contents before returning to x.cpp.

假设a.hpp仍然设法编译(也就是说,实际上并不需要c.hpp),那么a.hpp完成,然后b.hpp完成,然后c.hpp最终在返回x.cpp之前实际定义了它的内容。

The solution is to minimize the amount of headers you include. Use forward declarations, and most of all: do not use 'include everything' headers! These are terrible. And I suspect that's what Headers.hpp is.

解决方案是最小化您包含的标头数量。使用前向声明,最重要的是:不要使用'include everything'标题!这些都很可怕。而且我怀疑Headers.hpp是什么。

#2


1  

How about class Targetable : public ::players::Ownable { . . .?

类Targetable怎么样:public :: players :: Ownable {。 。 。?

Note the global namespace qualification :: before players.

注意球员之前的全局命名空间限定::

#1


3  

You have a circular include.

你有一个循环包括。

First consider the purpose of include guards:

首先考虑包括警卫的目的:

// 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"

The inclusion of c.hpp will end up include a.hpp twice. The first time, the guards are not defined and everything is okay, and the second time the guards prevent redefinitions. This is what we want.

包含c.hpp最终将包括a.hpp两次。第一次,守卫没有定义,一切都很好,第二次守卫阻止重新定义。这就是我们想要的。

This does not work when you have a loop, though. (It will prevent it, which is good, but it does "too well" because the guard is defined right after its tested, which means the contents of the header haven't actually yet been processed). Consider this instead:

但是,当你有一个循环时,这不起作用。 (它会阻止它,这很好,但它确实“太好了”,因为防护是在测试后立即定义的,这意味着标头的内容实际上还没有被处理过)。请考虑一下:

// 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"

Which is similar to what you have. x.cpp includes c.hpp, which is the first time it's been included so it defines C_HPP. Then c.hpp includes b.hpp, which includes a.hpp. Then a.hpp includes c.hpp and finds that C_HPP has already been defined, so the include does nothing.

这和你的相似。 x.cpp包含c.hpp,这是第一次包含它,因此它定义了C_HPP。然后c.hpp包含b.hpp,其中包括a.hpp。然后a.hpp包含c.hpp并发现已经定义了C_HPP,因此include不执行任何操作。

Assuming a.hpp still manages to compile (that is, c.hpp isn't actually needed), then a.hpp finishes, then b.hpp finishes, then c.hpp finally actually defines its contents before returning to x.cpp.

假设a.hpp仍然设法编译(也就是说,实际上并不需要c.hpp),那么a.hpp完成,然后b.hpp完成,然后c.hpp最终在返回x.cpp之前实际定义了它的内容。

The solution is to minimize the amount of headers you include. Use forward declarations, and most of all: do not use 'include everything' headers! These are terrible. And I suspect that's what Headers.hpp is.

解决方案是最小化您包含的标头数量。使用前向声明,最重要的是:不要使用'include everything'标题!这些都很可怕。而且我怀疑Headers.hpp是什么。

#2


1  

How about class Targetable : public ::players::Ownable { . . .?

类Targetable怎么样:public :: players :: Ownable {。 。 。?

Note the global namespace qualification :: before players.

注意球员之前的全局命名空间限定::