命名空间

维基百科,自由的百科全书
跳转至: 导航搜索

命名空间英语Namespace)表示标识符(identifier)的可见范围。一个标识符可在多个命名空间中定义,它在不同命名空间中的含义是互不相干的。这样,在一个新的命名空间中可定义任何标识符,它们不会与任何已有的标识符发生冲突,因为已有的定义都处于其它命名空间中。

例如,设Bill是X公司的员工,工号为123,而John是Y公司的员工,工号也是123。由于两人在不同的公司工作,可以使用相同的工号来标识而不会造成混乱,这里每个公司就表示一个独立的命名空间。如果两人在同一家公司工作,其工号就不能相同了,否则在支付工资时便会发生混乱。

这一特点是使用命名空间的主要理由。在大型的计算机程序文档中,往往会出现数百或数千个标识符。命名空间(或类似的方法,见“命名空间的模拟”一节)提供一隱藏區域標識符的機制。通过将逻辑上相关的标识符组织成相应的命名空间,可使整个系统更加模块化

编程语言中,命名空间是对作用域的一种特殊的抽象,它包含了处于该作用域内的标识符,且本身也用一个标识符来表示,这样便将一系列在逻辑上相关的标识符用一个标识符组织了起来。许多现代编程语言都支持命名空间。在一些编程语言(例如C++Python)中,命名空间本身的标识符也属于一个外层的命名空间,也即命名空间可以嵌套,构成一个命名空间,树根则是无名的全局命名空间

函数的作用域可被視作隱式命名空间,它們和可見性、可訪問性和对象生命周期不可分割的联系在一起。

C++中的命名空间[编辑]

C++语言中,命名空间是一种实体,使用namespace来声明,并使用{ }来界定命名空间的作用域。

namespace foo {
  int bar;
}

命名空间对应于命名空间作用域。和C语言文件作用域兼容,C++具有全局命名空间作用域,对应的命名空间是全局命名空间,不需要声明。用前缀为::的qualified-id显式引用全局命名空间作用域中的名称,此外也有特别的用法。例如,::operator new指称全局new运算符;而::new指称new表达式使用全局::operator new为创建的对象分配存储。

命名空间可以在另一命名空间之中嵌套声明;但不能声明在类和代码块之中。在命名空间中声明的名称,默认具有外部链接(除非声明的是const对象,它默认是具有内部链接)。

按照是否有名字,可分为有名字的命名空间与无名命名空间。后者的声明为:

namespace {
              namespace-body(即声明序列(可选)}

实现会选取一个和其它命名空间名称都不一样的唯一隐含名称为其命名。无名命名空间的成员在本翻译单元中可以不加显式引用(实际上也没法显式引用无名命名空间)而直接使用;但在其他翻译单元中不可见。尽管无名命名空间中的名称仍然具有默认的外部链接,但因为无法和其它命名空间中的名称一样被跨翻译单元引用,可以和静态链接的名称类似被优化。

命名空间的成员,是在命名空间体的花括号内声明了的名称。可以在命名空间体之外,给出命名空间成员的定义。即命名空间的成员声明与定义可以分开。

子命名空间必须定义在上层命名空间体之内。禁止把子命名空间的声明与定义分开。

不能以“命名空间名::成员名;”方式,在命名空间体之外为命名空间添加新成员。必须在命名空间体之中添加新成员的声明。

可以多次声明和定义同一命名空间,每次给这一命名空间添加新成员。同名的命名空间即便在声明位置不同,仍然是同一个实体。

可以在一个命名空间中引入其他命名空间的成员。例如:

namespace myNameSpace{
       using namespace His_NameSpace;
       using OLib::List;
       void my_func(String &, List &);
}

引用命名空间的成员,有下述办法:

  • 使用命名空间的作用域解析运算符::,如:std::cout
  • using namespace 命名空间名[::命名空间名…];该语句使指定的命名空间中的所有成员都可直接使用。如果引入的名称与局部名称发生冲突,则编译器并不会发出任何警告信息,而只是用局部名称自动覆盖命名空间中的同名成员。
  • using 命名空间名::[命名空间名::……]成员名; 引入命名空间中的一个成员。如果引入的名称与局部名称发生同名冲突,编译器会报错。

命名空间可以有别名:namespace 别名 = 命名空间名; 这使得名字较长的命名空间可以方便地用较短的别名来引用。

C++11起支持内联命名空间。使用inline namespace作为声明的起始。内联命名空间的名称在名称查找时被特别对待,使用qualified-id引用其中的名称时,被内联的命名空间名称可以省略。实用上,内联命名空间可以在修改命名空间名称的同时避免在二进制文件中生成的符号改变,因此不同内联命名空间的名称可以用于标识接口兼容的不同版本,有助于保持二进制兼容性。这也在标准库的实现中被使用,如libstdc++和libc++。

在XML中的应用[编辑]

XML虽然不是一个独立的编程语言,但是它的出现使得命名空间的使用变得更为广泛。

在同一个命名空间裡,所有的元素名都必须唯一。

声明一个命名空间使用XML保留的属性xmlns,它的值必须是URI(统一资源标志符 Uniform Resource Identifier而非URL--Universal Resource Locator)指代.比如xmlns="http://www.w3.org/1999/xhtml".注意,事实上URI是不可读的,但它对XML解析器来说就只是简单不过的字串.比如,http://www.w3.org/1999/xhtml/ 这个地址本身并不包含任何代码,它只表示XHTML命名空间.使用URI (比如"http://www.w3.org/1999/xhtml")去标示一个命名空间,而不是用一个简短的字串 (比如"xhtml"),这样做是为了减少不同命名空间标示符冲突的可能性.

命名空间的模拟[编辑]

参见[编辑]

外部链接[编辑]