命名空间(namespace)是一种用于减少C++程序中名字冲突的机制。在使用了第三方软件库的大程序中,名字冲突是一个常常需要提及的话题。在你自己的程序中,可以选择是否使用命名空间。
通常,我们把命名空间放在头文件中所声明的周围,以确保在该头文件中声明的所有标识符不会与全局命名空间中的标识符相冲突。例如:
#ifndef SOFTWAREINC_RANDOM_H
#define SOFTWAREINC_RANDOM_H
namespace SoftwareInc
{
extern int randomNumbers[128];
void populateRandomArray();
}
#endif
(需要注意的是,为了避免多重包含,我们对预处理器宏也进行了重命名,以便降低与不同目录中具有同样名字的头文件的冲突可能性。)
命名空间的语法与类的语法相仿,但是它不以分号结尾。这里是random.cpp文件的新形式:
#include "random.h"
int SoftwareInc::randomNumbers[128];
static int seed = 42;
static int nextRandomNumber()
{
seed = 1009 + (seed * 2011);
return seed;
}
void SoftwareInc::popularRandomArray()
{
for(int i = 0; i < 128 ; ++i)
{
randomNumbers[i] = nextRandomNumber();
}
}
与类不同,可以在任何时候“重新打开”命名空间。例如:
namespace Alpha
{
void alpha1();
void alpha2();
}
namespace Beta
{
void beta1();
}
namespace Alpha
{
void alpha3();
}
这就使定义许许多多的类成为可能,可以把这些类放在多个头文件中,然后再由这些文件构成一个命名空间。利用这一技巧,C++标准库就把它的所有所有标识符都放在std命名空间中。在QT中,命名空间用作类似于全局形式的标识,比如Qt::AlignBottom和Qt::yellow。由于历史原因,类Qt不属于任何命名空间,但它使用字母“Q”作为类的开头。
要在命名空间外部引用该命名空间中的一个标识符,可以把命名空间(和一个::)作为该表示的前缀。或者,也可以使用以下三种机制之一来做到这一点,这三种方法的目的都是为了尽量减少敲击键盘的次数。
- 定义命名空间的别名
namespace ElPuebloDeLaReinaDeLosAngeles
{
void beverlyHills();
void culverCity();
void malibu();
void santaMonica();
}
namespace LA = ElPuebloDeLaReinaDeLosAngeles;
在定义了别名之后,就可以用这个别名代替它原有的名字了。
- 命名空间中导入了一个简单的标识符
int main()
{
using ElPuebloDeLaReinaDeLosAngeles::beverlyHills;
beverlyHills();
...
}
这里的using声明可以让我们从一个命名空间中访问某个给定的标识符,而不用再把该命名空间作为标识符的前缀。
3. 只用一条指令导入整个命名空间
···
int main()
{
using namespace ElPuebloDeLaReinaDeLosAngeles;
santaMonica();
malibu();
...
}
使用了这种方法,似乎就更容易产生名字冲突了。如果编译器抱怨有二义性的名字(例如,在两个不同命名空间中定义了两个具有相同名字的类),那么在需要引用这个名字的时候,通常就要使用命名空间来限定这个标识符。
网友评论