2.3.2 名字空间
正如第1章所提到的那样,在C语言中,当程序达到一定规模之后,会遇到的一个问题是我们“用完了”函数名和标识符。当然,并非我们真正用完了所有函数名和标识符,而是简单地想出一个新名称就不太容易了。更重要的是,当程序达到一定的规模之后,通常分成许多块,每一块由不同的人或小组来构造和连接。由于所有的函数名和标识符都在同一程序里,这就要求所有的开发人员都必须非常小心,不要碰巧使用了相同的函数名和标识符,导致冲突。这种情况很快变得令人烦躁,而且浪费时间,最终导致高昂的代价。
标准的C++有预防这种冲突的机制:namespace关键字。库或程序中的每一个C++定义集被封装在一个名字空间中,如果其他的定义中有相同的名字,但它们在不同的名字空间,就不会产生冲突。
名字空间是十分方便和有用的工具,但名字空间的出现意味着在写程序之前,必须知道它们。如果只是简单地包含头文件,使用头文件中的一些函数或对象,编译时,可能会遇到一些奇怪的错误,确切地说,如果仅仅只包含头文件,编译器无法找到任何有关函数和对象的声明。在多次看到编译器的这种提示后,我们会熟悉它所代表的含义(即“虽然包含了头文件,但所有的声明都在一个名字空间中,而没有告诉编译器我们想要用这个名字空间中的声明)。
可以用一个关键字来声明:“我要使用这个名字空间中的声明和(或)定义”。这个关键字是“using”。所有的标准C++库都封装在一个名字空间中,即“std”(代表“standard”)。由于本书常使用到这些标准的库文件,几乎在每个程序中都有如下的使用指令(using指令):
这意味着打开std名字空间,使它的所有名字都可用。有了这条语句,就不用担心特殊的库组件是在一个名字空间中,因为在使用using指令地方,它使名字空间在整个文件中都是可用的。
在人们费尽心机把名字空间的名字隐藏起来之后,再暴露名字空间的所有名字,这看起来是矛盾的,而事实上,应该对这样的轻率作法倍加小心(这将在本书后面解释)。但是,using指令仅暴露当前文件的名字,所以,它并不像起初听起来那样严重(但是,如果再想一想在头文件中这样做,这就是鲁莽的举动)。
名字空间和包含头文件的方法之间存在着相互关系。现代头文件的包含命令已标准化了(如<iostream>,不带扩展名“.h”),过去典型包含头文件的方式是带上“.h”,如<iostream.h>。那时,名字空间不是语言的一部分。所以,对已经存在的代码要提供向后兼容,如果给出
它相当于
但本书使用标准的包含格式(即不带“.h”),因此就必须显式地使用using指令。
到此,介绍了对名字空间必须了解的内容,在第10章将更全面地讨论这个问题。