为什么需要命名空间
命名空间是ANSI C++引入的可以由用户命名的作用域,用来处理程序中常见的同名冲突。
作用域:
在C语言中定义了3个层次的作用域:文件(编译单元)、函数和复合语句。C++引入了类作用域,类是出现在文件内。在不同的作用域中可以定义相同名字的变量,互不干扰便于系统区别他们。
注:全局变量的作用域是整个程序,在同一个作用域中不应有两个或多个同名的实体(entity)包含函数、变量和类
常见作用:
如果在文件中定义了两个类,在这两个类中可以有同名的函数,在引用时,为了区别,应该加上类名作为限定。
实际工程应用中:
由于一个大型的应用软件是往往由若干个人合作组成一个完整的程序,可能在不同的头文件中用了相同的名字来命名所定义的类或函数。这样在程序中就会出现命名冲突(即重复定义)。由于需要应用一些库,其中包含C++编译系统提供的库、由软件开发商提供的库、或是用户自己开发的库,的时候可能会出现“全局命名空间污染”:如果在这些库中包含与程序的全局实体同名的实体,或者不同的库中含有相同的实体名。
早期解决方法:
将实体名字写长、以特殊字符作为名字、由编译系统提供的内部全局标识符都用下划线作为前缀、由软件开发商提供的实体名字以特定字符作为前缀。但是可读性变差了,增加了阅读的难度。
后来,SNSI C++提供了一种机制、一种工具使由库的设计者命名的全局标识符能够和程序的全局实体名以及其他类的全局标识符区分开来——命名空间
什么是命名空间
命名空间,实际上就是一个由程序设计者命名的内存区域。程序设计者可以根据需要制定一些有名字的空间域,将一些全局实体分别放在各个命名空间中,从而实现与其他全局实体分割开。
namespace ns1//指定命名空间ns1
{
int a;
double b;
}
关键词:namespace 为定义命名空间的关键词
命名空间的名字:如此例中的ns1
命名空间成员:花括号内为声明块,声明的实体称为命名空间成员,其中包括变量(可以带有初始化)、常量、函数(可以是定义或声明)、结构体、类、模板、命名空间(在一个命名空间中又定义一个命名空间,即嵌套的命名空间)
命名空间限定:在使用的变量名前面加上命名空间名和作用域分辨符::的用法(如ns1::a,也被称为被限定名)
命名空间的作用和使用
命名空间的作用:
建立了一些相互分隔的作用域,将一些全局实体分隔开来,以免产生名字冲突.
可以根据需要设置多个命名空间,每个命名空间代表一个不同的命名空间域,不同的命名空间不能同名。
注:过去用的全局变量可以理解为全局命名空间,独立于所有有名的命名空间之外,他是不需要用namespace声明的,实际上是由系统隐式声明的,存在于每个程序之中。
namespace ns1
{
const int RATE =0.08 //常量
double pay; //变量
double tax() //函数
{
return a*RATE;
}
namespace ns2 //嵌套的命名空间
{
int age;
}
}
与类的声明方法和使用方法的区别:
在声明类时,在右花括号的后面有一个分号,而在定义命名空间时,花括号的后面没有分号。
注意:命名空间中的内容是不能包括预处理指令的,也就是#include指令等,不然编译会报错
使用命名空间成员的方法
在引用命名空间成员时要用命名空间名和作用域分辨符对命名空间成员进行限定,以区分不同的命名空间中的同名标识符
命名空间名::命名空间成员名
如果命名空间名过较长,在有命名空间嵌套情况下,为引用一个实体需要写很长的名字。如果在程序中多次引用命名空间成员就会感到很不方便。
1.使用命名空间别名
为命名空间起一个别名,用来代替较长的命名空间名
namespace Television
{
...
}
namespace TV =Televison;//别名TV指向原名Televison,在原来出现Television的位置都可以无条件使用TV代替
2.使用“using 命名空间成员名”
using后面的命名空间名必须是由命名空间限定的名字
using声明的有效范围是从using开始到using所在的作用域结束
using ns1::Student;//在其后程序出现的Student就是隐含指ns1::Student
Student stud1(101,"Wang",18);
cout <
注:在同一作用域中用using声明的不同命名空间中的成员中不能有同名的成员。以避免二义性
using ns1::Student;
using ns2::Student;
Student stu1;//无法确定此处的Student时哪个命名空间中的student
3.使用“using namespace 命名空间名”
using namespace 命名空间名;
using namespace us1;
Student std1(101,"Wang",18);//Student隐含指命名空间ns1中的Student
cout
注:只有在使用命名空间数量很少,以及确保这些命名空间中没有同名成员时才使用using namespace语句。否则还是可能出现二义性,编译出错。
无名的命名空间
由于命名空间没有名字,在其他文件中显然无法引用,它只在本文件的作用域内有效。也就时说,无名命名空间的作用域为声明无名命名空间的位置开始到本文件结束。且在本文件中使用无名命名空间的成员,不必也无法用命名空间名限定。
namespace
{
void fun()
{
cout <<"OK" <
拓展:
在C语言中可以用static声明一个函数,使此函数的作用域仅限于本文件。c++不仅保留了用static声明函数的用法,同时提供了用无名命名空间来实现这一功能。
标准命名空间std
标准C++库中所有标识符都是在一个名为std的命名空间中定义的,或者说标准头文件(如iostream)中函数、类、对象和类模板是在命名空间std中定义的。std是standard(标准)的缩写,表示这是存放标准库的有关内容的命名空间,含义清楚,不必死记
using namespace std;
/*
如此可实现在std中定义和声明的所有标识符在本文件中都可以作为全局变量来使用
但是应当绝对保证在程序中不出现与命名空间std的成员同名的标识符,
为了避免因为命名空间std中定义的实体太多,程序编写者误定义了与命名空间std同名的实体,程序编写者喜欢用若干个"using 命名空间成员“声明来代替“using namespace命名空间”声明
*/
using std::string;
using std::cout;
using std::cin;
/*
为减少在每一个程序中都要重复书写以上的using声明,程序开发者往往将需要编写应用程序时经常用到命名空间std成员的using声明组成一个头文件,然后再程序中包含此文件就可以了。
*/
备注:
有些C++库是多年前开发的,当时并没有命名空间,标准库中的有关内容也没有放在std命名空间中,因为在程序中可以不对std进行声明,但是,今年来提供的C++标准库都是在命名空间std中声明(特点为C++的新标准头文件不带后缀.h的件文件),应当在程序中使用命名空间和using namespace语句,否则无法引用这些头文件。
参考资料:《C++程序设计》谭浩强