15.3.4 using编译指令

    前面介绍过通过using声明语句使得某个空间中的特定实体可见,using编译指令比using声明更进一步,通过“using namespace名称空间名;”的形式,使得名称空间中的实体都可见,不再需要作用域限定符。

    到此为止,几乎所有的示例代码都使用了下述语句。


    using namespace std;这是因为所有的C++标准库函数,都定义在名称空间std下,以头文件<iostream>为例,可以在其中找到如下代码。 _STD_BEGIN //OBJECTS static ios_base:Init_Ios_init; extern_CRTIMP istream cin; extern_CRTIMP ostream cout; extern_CRTIMP ostream cerr,clog; //CLASS_Winit class_CRTIMP_Winit{ public: _Winit(); ~_Winit(); private: static int_Init_cnt; }; //WIDE OBJECTS static_Winit_Wios_init; extern_CRTIMP wistream wcin; extern_CRTIMP wostream wcout,wcerr,wclog; _STD_END

    其中,_STD_BEGIN和_STD_END是两个宏,定义如下所示。


    #define_STD_BEGIN namespace std{ #define_STD_END};

    从中不难看出,头文件<iostream>中创建了名称空间std,包含了该头文件,便可以通过名称空间限定符在当前文件中使用输入输出流对象cout和cin,形式为“std:cout”和“std:cin”,如果觉得这样书写很麻烦,可以使用using声明机制,如下所示。


    using std:cout; using std:cin;

    当然,也可以使用using编译指令,即“using namespace std;”使得名称空间中当前有效的实体都可见,本书前面的示例代码中都采用了在外部使用using编译指令,使得cout和cin可以在程序中自由使用。

    为什么说是当前有效的实体,因为不仅是<iostream>中定义了namespace std,其他标准头文件中也定义了std,根据名称空间的开放性,添加的头文件越多,std越庞大,有效的实体也越多。

    对某个名称空间使用using编译指令时,同样要保证其可见和有效,不能出现先using编译,后来才创建该空间的情况,否则编译器会报错。

    注意

    只有新式头文件才支持名称空间特性,在旧式头文件中没有这项机制,关于头文件标准的变化请参考第2章中的相关内容介绍。

    using编译指令比using声明指令更为强大,付出的代价是更容易出现二义性。因此,使用using编译指令时要合理安排,避免多重声明。同时,名称空间的提出是为了大型程序的管理,使用using编译指令虽然很省力,但并不推荐使用它,using编译后会导致名称空间失效,这不是我们想看到的。