使用名字空间的成员,有两种方法:第一种是:使用using声明。第二种是使用using提示符。下面分别介绍这两种方法,以及这两种方法使用上的区别。
第一种:using声明
using声明的格式:
using声明以关键字using开头,后面是名字空间成员。using声明中的成员必须是限定修饰符名。例如:
using std::cin ;
using声明和其他的声明的行为一样:它有一个域,它引入的名字从该声明开始直到其所在的域结束都是可见的。using声明引入的名字有以下特性:
1、它在该域中必须惟一
2、有外围域中的声明引入的相同的名字被其隐藏
3、它被嵌套域中的相同的名字的声明隐藏
例如:
namespace blip
{
int bi = 16,bj = 15,bk = 23 ;
//其他声明
}
int bj = 0 ; //全局域定义的bj
void manip()
{
using blip::bi ; //函数manip中的bi指向blip::bi
++bi ; //设置blip::bi为17
using blip::bj ; //隐藏全局域中的bj,符合特性2
++bj ; //设置blip::bj为16
int bk ; //bk在局部域中声明
using blip::bk ; //错误:在manip中重复定义bk,这符合特性1
}
int wrongInit = bk ; //错误:bk在这里不可见,应该用blip::bk
第二种:using指示符
using指示符格式以关键字using开头,后面是关键字namespace,然后是名字空间名。例如:
using namespace std ;
using指示符使名字空间所有的成员可见。
请看下面的例子:
namespace blip
{
int bi = 16,bj = 15,bk = 23 ;
//其他声明
}
int bj = 0 ; //全局域定义的bj
void manip()
{
using namespace blip; //using指示符。::bj和blip::bj之间的冲突只在bj被使用时才检测到
++bi ; //设置blip::bi为17
++bj ; //错误:二义性。全局bj还是blip::bj
++::bj ; //OK:设置全局bj为1
++blip::bj ; //OK:设置blip::bj为16
int bk = 97 ; //局部bk隐藏blip::bk
++bk ; //设置局部bk为98
}
using指示符是域内的。在manip函数中的using指示符只能应用在manip函数的块内。对于manip函数来说,名字空间blip的成员就好像在全局域中声明的一样。这就意味着,manip函数中的局部声明可以隐藏某些名字空间成员。局部变量bk隐藏了名字空间blip::bk。在manip函数中引用bk没有二义性,它引用的是局部变量bk。但是变量bj会引起二义性。因为名字空间blip的成员就好像在全局域中声明的一样。
如果程序有很多的using声明,则可以创建一个头文件,使它包含该应用程序所需的名字空间成员的全部using声明,这样比较方便。该头文件将被包含在程序文件中的C++标准头文件之后。
下面是一个练习题:
namespace Exercise
{
int ival = 0 ;
double dval = 0 ;
const int limit = 1000 ;
}
int ival = 0 ;
//1
void manip()
{
//2
double dval = 3.1416 ;
int iobj = limit + 1 ;
++ival ;
++::ival ;
}
如果namespace Exercise的所有成员的using声明出现在//1或出现在//2,对程序代码中的声明和表达式有什么影响?现在针对namespace Exercise,以一个using提示符取代using声明,然后回答相同的问题。
解:
1、使用using声明
放在//1时:会造成对ival的重复定义
放在//2时:会造成对dval的重复定义
2、使用using提示符
放在//1时:会造成ival成为一个模棱两可的符号。不过,++::ival任然可以明确的对声明与全局域的ival的操作
放在//2时:由于manip内未操作dval,而模棱两可的错误只有在使用点上才会被侦测出来。所以dval身上不会模棱两可的错误。如果manip内操作了dval,任然不会有误。出现manip内的using提示符,会使Exercise::dval就像定义于全局域一样,会被manip内的dval会遮蔽该声明。