为什么需要命名空间
假设有一段程序模拟了班级点名的场景,且班级里存在同名学生。这时老师肯定不会直接喊名字,而会在同名的名字上加上某些标志或特征以示区别。
而程序是死脑筋的,它只会按照事先的设定按部就班的点名。并不会因为存在同名学生而应急处理(加个修饰区分等)。
可以这样粗糙地理解,这里的老师就是编译规则,学生就是变量。这种名字冲突的问题,则称为命名空间污染问题
1。
对于大型项目而言,一个项目经常需要划分为独立的子模块再合并。
而大部分人常用的命名是很容易雷同的。
C++
为我们提供了另一种方法,即命名空间
。
如何使用
以上文的例子,使用命名空间如下:
//老刘写的
namespace Liu{
int id;
//...
void fun();
}
//老郭写的
namespace Guo{
int id;
//...
void fun();
}
::
域解析操作符,在 C++
中用来指明要使用的命名空间。
因此在使用的时候则是: Liu::id
、Guo::id
注意:
命名空间可以在全局作用域或其他作用域内部定义,但不能在函数或类内部定义 1 。
命名空间内部不仅可以声明或定义变量,对于其它能在命名空间以外声明或定义的名称,同样也都能在命名空间内部进行声明或定义,例如类、函数、typedef
、#define
等都可以出现在命名空间中 2。
Using
在 C++
中我们经常能看到 std
,它其实是标准库的命名空间。
std::cout << "Hello Word ! " << std::endl;
上述为一标志输出,若在每次使用标准库时都加上命名空间,则显得异常繁琐。
毕竟偷懒是程序员的一大动力。
C++
提供了更简洁的方式来使用命名空间成员,即 using
。
该指令将告知编译器,后面的代码中,缺省的命名空间设置为 using
指定的命名空间,于是,上面的代码可以改写为:
using namespace std;
cout << "Hello Word ! " << endl;
此外, using
亦可针对某个变量/方法
using namespace Liu::id;
站在编译和链接的角度,代码中出现的变量名、函数名、类名等都是一种符号。有的符号可以指代一个内存位置,例如变量名、函数名;有的符号仅仅是一个新的名称,例如 typedef
定义的类型别名 2。
不连续命名空间
与作用域不同,命名空间可以是不连续的。命名空间由它的分离定义部分的总和构成,命名空间是累积的 1。
我们可以在 A文件
中增加 命名空间A
,在 B文件
中同样使用 命名空间A
,并增加一些内容。
namespace Liu{
int id;
//...
void fun();
}
即以上代码,既可以是定义新的命名空间,又可以是添加到现有的命名空间中。
值得注意的是:若命名空间中的某个组成部分需要请求定义在另一个文件中的名称,则仍然需要声明该名称 3。
嵌套命名空间
命名空间可以嵌套,您可以在一个命名空间中定义另一个命名空间,如下所示:
namespace namespace_name1 {
// 代码声明
namespace namespace_name2 {
// 代码声明
}
}
使用如下:
// 访问 namespace_name2 中的成员
using namespace namespace_name1::namespace_name2;
// 访问 namespace:name1 中的成员
using namespace namespace_name1;