C++ 匿名名称空间的GCC缺陷?

C++ 匿名名称空间的GCC缺陷?,c++,gcc,g++,anonymous,C++,Gcc,G++,Anonymous,我有两个来自main.cpp的头文件,它们在匿名命名空间中具有以下定义:const string strToken=(“%”) 使用g++版本4.9编译会产生以下结果: In file included from main.cpp:25:0: libraries/trace.h:31:14: error: redefinition of ‘const string {anonymous}::strToken’ const string strToken = ("%");

我有两个来自main.cpp的头文件,它们在匿名命名空间中具有以下定义:
const string strToken=(“%”)
使用g++版本4.9编译会产生以下结果:

In file included from main.cpp:25:0:
libraries/trace.h:31:14: error: redefinition of ‘const string {anonymous}::strToken’
 const string strToken = ("%");
              ^
In file included from libraries/debuglogger.h:12:0,
                 from libraries/packet.h:10,
                 from main.cpp:20:
libraries/strformat.h:23:14: note: ‘const string {anonymous}::strToken’ previously declared here
 const string strToken = ("%");
              ^

我曾认为,在匿名名称空间中放置某些内容会将其限制在文件范围内,因此这不是问题。我是否遗漏了什么,或者这是GCC中的某种缺陷?如果有人想要完整的代码,我愿意将其包括在内,但我希望我的问题中包含了足够的信息,不需要它。

我在做了一些研究后发现,在标题中使用匿名名称空间是个坏主意。请参阅此处以了解可能的解决方案:

在做了一些研究之后,我发现在标题中使用匿名名称空间是个坏主意。有关可能的解决方案,请参见此处:

我曾认为,将某些内容放入匿名名称空间会将其限制在文件范围内

你只是有点不对劲。将内容放在匿名名称空间中会限制它们对出现在其中的翻译单元的可见性。翻译单元是转换为单个对象文件的所有内容,通常是一个源文件(.cpp文件)以及源文件中包含的头文件中的所有代码。因此,如果main.cpp包含两个具有相同声明(在匿名命名空间中或不在匿名命名空间中)的头,则会出现错误

始终认为
#include
语句本质上只是标题内容的复制粘贴,而不是include语句。一旦你明白了这一点,这些问题就变得容易处理了。例如,您的特定情况基本上归结为在解析include语句(复制粘贴到源文件中)后拥有此代码:

其中错误非常明显,匿名名称空间实际上不会改变基本问题,即您对同一事物有多个定义

匿名名称空间主要用于在翻译单元(通常在.cpp文件本身中)内创建内容,而不会在将翻译单元编译到目标文件后出现它们的任何痕迹。您可能会发现理解整个编译和链接过程很有帮助

我曾认为,将某些内容放入匿名名称空间会将其限制在文件范围内

你只是有点不对劲。将内容放在匿名名称空间中会限制它们对出现在其中的翻译单元的可见性。翻译单元是转换为单个对象文件的所有内容,通常是一个源文件(.cpp文件)以及源文件中包含的头文件中的所有代码。因此,如果main.cpp包含两个具有相同声明(在匿名命名空间中或不在匿名命名空间中)的头,则会出现错误

始终认为
#include
语句本质上只是标题内容的复制粘贴,而不是include语句。一旦你明白了这一点,这些问题就变得容易处理了。例如,您的特定情况基本上归结为在解析include语句(复制粘贴到源文件中)后拥有此代码:

其中错误非常明显,匿名名称空间实际上不会改变基本问题,即您对同一事物有多个定义


匿名名称空间主要用于在翻译单元(通常在.cpp文件本身中)内创建内容,而不会在将翻译单元编译到目标文件后出现它们的任何痕迹。您可能会发现这有助于理解整个编译和链接过程。

为什么头文件中有匿名名称空间?对于每个include,内存中都会有一个“%”的副本。@NeilKirk所以我要退一步到这里。假设我不想将对该字符串的访问限制在头文件中。如果不使其成为类的私有成员或使用匿名名称空间,我如何才能做到这一点?从您的帖子中,我不确定您是否要将其从包含文件中隐藏或使其可用。@NeilKirk我希望它从包含文件中隐藏。理想情况下,它将仅在与此头文件关联的源文件中定义,除非您有模板代码、内联函数或依赖于它的默认参数。为什么在头文件中有匿名命名空间?对于每个include,内存中都会有一个“%”的副本。@NeilKirk所以我要退一步到这里。假设我不想将对该字符串的访问限制在头文件中。如果不使其成为类的私有成员或使用匿名名称空间,我如何才能做到这一点?从您的帖子中,我不确定您是否要将其从包含文件中隐藏或使其可用。@NeilKirk我希望它从包含文件中隐藏。理想情况下,它将仅在与此头文件关联的源文件中定义,除非您有模板代码、内联函数或依赖于它的默认参数。
// from first header:
namespace {
  const string strToken = ("%");
};

// from second header:
namespace {
  const string strToken = ("%");
};

int main() { ... };