在 C/C++ 的源文件中,为了对外隔离符号,即外界无法通过 extern
声明捕获到这个符号,我们一般会采用 static
声明的方式来处理这个符号。比如
// 采用static声明对外隐藏符号
static void internal_func();
static float internal_value;
这样, internal_func
和 internal_value
这两个符号对外就是不可见的了。一般情况下,隐藏符号只通过 static
声明就可以了,但 static
声明也有如下缺点:
1、static
无法修饰类型,比如这样的类型声明就是错误的。
// 注意:这段代码是非法的
static class Widget {
public:
...
};
因此,如果想要隐藏 Widget
这个类,就不能用 static
声明的方式。
2、static
这个关键词用处过多,在不同的地方修饰的变量,其含义完全不同,容易造成混淆。比如下面定义的三个 static
变量,其含义就完全不同
class Widget
{
private:
static float count;
};
static const float PI = 3.141592654;
void test()
{
static int i = 0;
...
}
3、由于 static
声明会使得符号没有外部链接属性,因此某些模板参数将不能使用这个符号,比如
template<typename T, const int& N>
class Widget
{
public:
...
private:
T data[N];
...
};
static const int kMaxSize = 30;
Widget<int, kMaxSize> w; // 报错,因为kMaxSize并不具备外部链接属性
为了克服上述三个缺点,就需要引入另一种隐藏符号的方式——匿名命名空间。我们先来看这样一段声明
// 采用匿名命名空间对外隐藏符号
namespace {
void internal_func();
float internal_value;
}
在这段声明中,注意我们并没有指定 namespace
是什么。这种没有为 namespace
指定名字的命名空间就是所谓的“匿名命名空间”。