未命名的命名空间如何优于静态关键字?

161
未命名的命名空间如何优于static关键字?

然而,根据标准委员会的说法,未命名的命名空间并不能完全替代命名空间静态。在一些情况下,例如这里,未命名的命名空间会失败,只有static才能正常工作。 - legends2k
2个回答

169
您所提到的是 C++03 标准的第 §7.3.1.1/2 节,该节指出声明命名空间中对象时已经不建议使用 static 关键字了,未命名的命名空间提供了更好的替代方案。请注意,这段内容在 C++11 中已经被删除,按照标准,静态函数不再是过时的了!尽管如此,未命名的命名空间仍然比 static 关键字更优,主要原因是关键字 static 只适用于变量声明和函数,而不适用于用户定义的类型。以下代码在 C++ 中是有效的:
//legal code
static int sample_function() { /* function body */ }
static int sample_variable;

但是这段代码是无效的:

//illegal code
static class sample_class { /* class body */ };
static struct sample_struct { /* struct body */ };

因此解决方案是未命名(也称为匿名)namespace,其如下所示:
//legal code
namespace 
{  
     class sample_class { /* class body */ };
     struct sample_struct { /* struct body */ };
}

希望这能解释为什么匿名的 namespacestatic 更好。


12
更普遍地说,未命名的命名空间允许外部链接。这使局部到翻译单元的类声明成为可能。它还允许例如外部链接字符串常量被用作模板参数。 - Cheers and hth. - Alf
10
正如Fred Nurk在您的另一个回答中指出的那样,最新的C++0x FCD(n3225)已经移除了这个“deprecated(不推荐使用)”的注释。 - Matthieu M.
45
你正在回答自己的问题并感谢自己。 :-o - manpreet singh
13
如果只在cpp文件中定义类(没有匿名命名空间,没有static修饰),与使用匿名命名空间和static修饰时有什么不同? - Luchian Grigore
6
在第二个.cpp中,链接错误是由于定义了一个与之前相同名称的类所致。 - Xaqq
显示剩余6条评论

11

这涉及到一个有趣的问题:

假设您使用 static 关键字或未命名的 namespace 使某些函数对模块(翻译单元)内部可见,因为该函数旨在仅在模块内部使用,而不可在模块外部访问。(未命名的 namespace 还具有使数据和类型定义内部化的优点,除了函数以外)。

随着实现您的模块的源文件逐渐变大,您可能希望将其拆分为几个单独的源文件,这将有助于更好地组织代码,更快地找到定义,并独立编译。

但是现在您面临一个问题:那些函数不能再被看作是对模块 static 的,因为 static 实际上指的是 源文件(翻译单元),而不是 模块。 您必须使它们非 static,以允许从该模块的其他部分(目标文件)访问它们。但这也意味着它们不再隐藏/私有于该模块:由于具有外部链接,它们可以被其他模块访问,这不是您最初的意图。

未命名的namespace也无法解决这个问题,因为它也是针对特定源文件(翻译单元)定义的,无法从外部访问。

如果能够指定某些namespaceprivate,那就太好了,也就是说,其中定义的任何内容都是模块内部使用的。但当然,C++没有"模块"这样的概念,只有与源文件紧密绑定的"翻译单元"。


3
这个办法很糟糕,而且是一个有限的解决方案,但你可以将包含内部静态或命名空间函数的cpp文件放入“主”cpp文件中,然后在构建时排除这些“卫星”cpp文件即可完成。唯一的问题是如果你有两个或更多的“主”cpp文件,并且它们都想使用其中一个“卫星”cpp文件中的某个很棒的函数... - Sergey
使用私有/受保护/公共的静态函数与继承不是解决方案吗? - Ali
1
C++20 引入了模块,这可以解决你的问题。 - L. F.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接