1.为什么引入名称空间:
大型程序往往是由团队开发的,即使是个人编写的程序,随着代码量的增多,变量、函数、类的名字冲突的现象时有发生,有的情况下,编译器会指明错误所在,但有时候会发生一些察觉不到的覆盖,让程序员对出现的错误摸不着头脑。
很多厂商提供了快捷的第3方类库,用户不用关心库中的类是如何实现的,知道如何调用接口使用即可,但多个厂商定义的变量、函数和类的名字可能会发生冲突,同样是初始化操作,甲公司类库提供了initial函数,乙公司可能也提供了initial函数,如果在程序中同时使用了两个公司的类库,initial函数对应哪个版本呢?
为了解决这些问题,新的C++标准提供了名称空间机制。旧标准中(ANSI/ISO 1998)并没有该项机制,所以,一些特别老的编译器可能并不支持名称空间特性。
很多厂商提供了快捷的第3方类库,用户不用关心库中的类是如何实现的,知道如何调用接口使用即可,但多个厂商定义的变量、函数和类的名字可能会发生冲突,同样是初始化操作,甲公司类库提供了initial函数,乙公司可能也提供了initial函数,如果在程序中同时使用了两个公司的类库,initial函数对应哪个版本呢?
为了解决这些问题,新的C++标准提供了名称空间机制。旧标准中(ANSI/ISO 1998)并没有该项机制,所以,一些特别老的编译器可能并不支持名称空间特性。
2.名称空间的定义和使用方式:
定义:
C++中定义名称空间的基本格式为:
namespace 名称空间名
{
变量类型 变量;
函数返回类型 函数原型;
}
定义在名称空间中的变量或者函数都称为实体
名称空间中的实体作用域是全局的, 并不意味着其可见域是全局的
如果不使用作用域限定符和using机制,抛开名称空间嵌套和内部屏蔽的情况,实体的可见域是从实体创建到该名称空间结束
在名称空间外,该实体是不可见的。
namespace 名称空间名
{
变量类型 变量;
函数返回类型 函数原型;
}
定义在名称空间中的变量或者函数都称为实体
名称空间中的实体作用域是全局的, 并不意味着其可见域是全局的
如果不使用作用域限定符和using机制,抛开名称空间嵌套和内部屏蔽的情况,实体的可见域是从实体创建到该名称空间结束
在名称空间外,该实体是不可见的。
使用方式:
作用域限定符
using声明机制
using编译指令
using声明机制
using编译指令
Example:
作用域限定符访问其实体:
#include <iostream>
using namespace std;
namespace A //创建名称空间A
{
void dispA()
{
cout<<"This is A"<<endl;
}
}
namespace B //创建名称空间B
{
void dispB()
{
A::dispA(); //名称空间A中的dispA函数
cout<<"This is B"<<endl;
}
}
int main()
{
B::dispB(); //名称空间B中的dispB函数
return 0;
}
全局using声明
#include <iostream>
using namespace std;
namespace A //创建名称空间A
{
void dispA()
{
cout<<"This is A"<<endl;
}
}
using A::dispA; //全局using声明语句,dispA等价于全局变量,(细节地方,声明不需要函数括号,例如using std::cin)
void dispEx() //全局函数
{
cout<<"This is outside"<<endl;
}
namespace B //创建名称空间B
{
void dispB()
{
dispEx();
dispA();
cout<<"This is B"<<endl;
}
}
int main()
{
B::dispB();
dispA();
return 0;
}
局部using声明
#include <iostream>
using namespace std;
namespace A //创建名称空间A
{
int num=0;
}
void disp() //全局函数
{
using A::num; //局部using声明
cout<<num<<endl;
}
int main()
{
disp();
return 0;
}
using声明机制使得某个空间中的特定实体可见,using编译指令比using声明更进一步,通过 “using namespace 名称空间名;”的形式,使得名称空间中的所有实体都可见,不再需要作用域限定符。如:using namespace std;