大型程序往往会使用多个库,这些库有大量的全局名字,不可避免的发生某些名字相互冲突。多个库将名字放置在全局命名空间中将引发命名空间污染。
命名空间为防止名字冲突提供了更加可控的机制。命名空间分割了全局命名空间,其中每个命名空间是一个作用域。
定义命名空间
namespace cplusplus_primer {
class A {};
A operator+(const A&, const A&);
...
}
定义了一个名为cplusplus_primer的命名空间。
命名空间可以定义在全局作用域内,也可以定义在其他命名空间中。但是,不能定义在函数或类的内部。
命名空间作用域后面无须分号。
每个命名空间都是一个作用域
不同命名空间的作用域不同,所以不同命名空间内可以有相同名字的成员。
定义在一个命名空间中的名字可以被该命名空间中的其他成员直接访问,也可以被这些成员内嵌作用域中的任何单位访问。
在命名空间外访问,必须明确指出所用的名字属于哪个命名空间:
cplusplus_primer::A a;
命名空间可以是不连续的
命名空间可以定义在几个不同的部分,这点与其他作用域不同。
有一点需要注意的是,不应该将#include放在命名空间内部。例如,
namespace my_space{
#include <string>
...
}
程序将会出错,隐含的意思是把头文件string中所有的名字定义成my_space空间的成员。意味着将命名空间std嵌套在命名空间my_space中。
可以在命名空间外定义类的成员。必须声明在作用域内,例如
在头文件.h中声明一个类和其成员函数,在同名的.cpp文件中进行函数的定义。但是,在.cpp文件中需要在函数前声明空间使用 ::
全局命名空间
全局作用域中定义的名字(即在所有类、函数和命名空间外的定义的名字)也就是定义在全局命名空间中。全局命名空间以隐式方式声明,并且在所有程序中都存在。全局作用域中定义的名字被隐式添加到全局命名空间中。
::member_name
表示全局命名空间中的一个成员。
使用命名空间成员
命名空间的别名
namespace cplus_plus{
/*...*/
};
namespace primer = cplus_plus;
使primer和cplus_plus等价。
使用using
using的命名空间中的成员与其他命名空间中的名字可能有冲突,这种冲突允许存在,但是如果想使用冲突的名字,必须明确指出名字的版本。
#include <iostream>
namespace my_name{
int i = 1, j = 2;
}
namespace your_name{
int i = 0;
}
有如上两个命名空间,在main函数中
int main(){
using namespace my_name;
using namespace your_name;
cout << i << endl;
return 0;
}
会产生错误,需要用::指明使用的是哪个命名空间中的变量。如果cout的是j就不会报错,命名空间中只有一个j。