匿名命名空间的 GCC 缺陷?

GCC Defect with anonymous namespaces?

我从 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 中的某种缺陷?如果有人想要完整的代码,我愿意将其包括在内,但我希望我已经在我的问题中包含了足够的信息而不需要它。

经过一些研究后我发现 headers 中的匿名名称空间不是一个好主意。请参阅此处了解可能的解决方案:Hiding a C++ class in a header without using the unnamed namespace

I had thought that putting something in an anonymous namespace limited it to file scope

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

始终将 #include 语句视为本质上只是 header 内容的 copy-paste,而不是 include 语句。一旦你理解了这一点,这些类型的问题就会变得更容易处理。例如,您的特殊情况基本上可以归结为在 include-statement 已解决(copy-pasted 到源文件)之后拥有此代码:

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

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

int main() { ... };

错误非常明显,匿名命名空间真的不会改变您对同一事物有多个定义的基本问题。

主要是匿名名称空间,这样您就可以在翻译单元(通常在 .cpp 文件本身)中创建内容,而不会在将翻译单元编译成 object 文件后出现任何痕迹.您可能会发现 this tutorial 有助于理解整个编译和链接过程。