未命名的命名空间如何优于static
关键字?
2 回答
您基本上是指 C++03 标准中的第 7.3.1.1/2 节,
在命名空间范围内声明对象时,不推荐使用 static 关键字;unnamed-namespace 提供了一个更好的选择。
请注意,此段落已在 C++11 中删除。static
功能按标准不再被弃用!
尽管如此, unnamednamespace
优于 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 */ };
}
希望它能解释为什么 unnamednamespace
优于static
.
有一个与此相关的有趣问题:
假设您使用static
关键字或未命名namespace
来使模块内部的某些函数(翻译单元),因为此函数旨在由模块内部使用,而不能在模块外部访问。(除了函数之外,Unnamednamespace
还具有使数据和类型定义在内部的优点)。
随着时间的推移,你的模块实现的源文件变得越来越大,你想把它分成几个单独的源文件,这样可以更好地组织代码,更快地找到定义,并且可以独立编译。
但是现在你面临一个问题:那些函数不能再static
指向模块,因为static
实际上并不是指向模块,而是指向源文件(翻译单元)。您被迫将它们static
设为非允许从该模块的其他部分(目标文件)访问它们。但这也意味着它们不再对模块隐藏/私有:具有外部链接,可以从其他模块访问它们,这不是您的初衷。
Unnamednamespace
也不能解决这个问题,因为它也是为特定的源文件(翻译单元)定义的,不能从外部访问。
如果可以指定 some namespace
is private
,那就太好了,也就是说,其中定义的任何内容都旨在由其所属的模块在内部使用。但是当然 C++ 没有“模块”这样的概念,只有“翻译单元”,它们与源文件紧密绑定。