【问题标题】:Anonymous namespace - has sense in both headers and code files?匿名命名空间 - 在头文件和代码文件中都有意义吗?
【发布时间】:2013-09-02 04:14:23
【问题描述】:

test.cpp

#include "test.hpp"

void f1() { }

namespace {
   void f2() {}
}

namespace test {
   void f3() { }
}

如果我错了,请纠正我,但是:

  • f1 可以从外部调用,如果它在头文件中声明使用extern 语句
  • f2 无法从外部调用
  • f3 可以从外部调用,如果它在头文件中声明(并适当地加上前缀 - test::)。如果没有在header中声明,就不能调用?

我说的对吗?

【问题讨论】:

  • 客户端可以声明f1和f3,即使你不...

标签: c++ namespaces visibility


【解决方案1】:

您的问题标题具有误导性。永远不要在标头中放置匿名命名空间。

f2 不能从 test.cpp 外部调用,正确。

如果有适当的声明,可以调用f1f3。这些可以在标头中,但没有什么能阻止其他 .cpp 文件简单地在标头中包含 的代码,即使您没有提供。

另外,函数声明不需要extern

void f1();
namespace test {
  void f3();
}

【讨论】:

  • 永远不要在标题中放置匿名命名空间。 - 为什么?
  • 除了其中的函数被无用地复制到包含头文件的每个 cpp 文件中外,它还在某些情况下产生了非常微妙的问题,例如如果您在该标头中有一个内联函数,该函数不在匿名命名空间中,而是使用匿名命名空间中的某些内容。我知道在一种情况下这样做是正确的,但它非常罕见和微妙,除非你要编写复杂的纯头文件库,比如 Boost 中的那些,否则你不会需要它。对于 99.99% 的 C++ 程序员来说,“从不”是他们唯一需要的规则。
  • 为什么你不应该ever将匿名(或未命名)命名空间放在标题中? Boost 正是通过 _1_2 等、bind 占位符实现的。这意味着每个翻译单元最终都有自己的名称空间中的任何内容的副本。此外,为了迂腐,您可以从另一个 TU 调用 f2()如果您可以获得编译器生成的命名空间名称。这是因为f2() 确实有外部链接。实际上这是不可能的,因为无法获得自动生成的名称。 (好吧,我看到你在我输入这条评论时提到了标题的例外情况)
  • @Praetorian 这就是我所说的一种情况,但请注意,当使用占位符的未命名命名空间之外的内联函数存在时,Boost.Bind 的使用在技术上被批评为导致未定义的行为。这就是我说微妙问题的原因。
  • 似乎我对 linkage of names within unnamed namespaces 的看法是错误的,C++11 中的规则已更改,因此这些现在具有内部链接。
猜你喜欢
  • 2016-11-01
  • 2010-09-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-10
  • 1970-01-01
  • 2010-11-04
相关资源
最近更新 更多