C++新增了这样一种功能,即通过定义一种新的声明区域来创建命名的名称空间,这样做的目的之是提供一个声明名称的区域。一个名称空间中的名称不会与另外一个名称空间的相同名称发生冲突,同时允许程序的其他部分使用该名称空间中声明的东西。例如,下面的代码使用新的关键字 namespace创建了两个名称空间:Jack和Jil.

  1. namespace Jack
  2. {
  3. double pail; //valiable declaration
  4. void fetch(); //function prototype
  5. int pal; //valiable declaration
  6. struct Well{...}; //struct declaration
  7. }
  8. namespace Jill
  9. {
  10. double bucket(double n){...}; //function declaration
  11. double fetch; //valiable prototype
  12. int pal; //valiable declaration
  13. struct Hill{...}; //struct declaration
  14. }

名称空间可以是全局的,也可以位于另一个名称空间中,但不能位于代码块中。因此,在默认情况下,在名称空间中声明的名称的链接性为外部的(除非它引用了常量).
除了用户定义的名称空间外,还存在另一个名称空间—全局名称空间( global namespace)。它对应于文件级声明区域,因此前面所说的全局变量现在被描述为位于全局名称空间中。
任何名称空间中的名称都不会与其他名称空间中的名称发生冲突。因此,Jack中的 fetch可以与Jll中的 fetch共存,Jl中的Hil以与外部Hil共存。名称空间中的声明和定义规则同全局声明和定义规则相同。
名称空间是开放的(open),即可以把名称加入到已有的名称空间中。例如,下面这条语句将名称go添加到Jill中已有的名称列表中:

  1. namespace Jill
  2. {
  3. char* goose(const char*);
  4. }

同样,原来的Jack名称空间为 fetch()函数提供了原型。可以在该文件后面(或另外一个文件中)再次使用Jack名称空间来提供该函数的代码:

  1. namespace Jack
  2. {
  3. void fetch()
  4. {
  5. ...
  6. }
  7. }

当然,需要有一种方法来访问给定名称空间中的名称。最简单的方法是,通过作用域解析运算符::,使用名称空间来限定该名称:

  1. Jack::pail = 12.34 //use a variable
  2. Jill::Hill mole //create a type Hill structer
  3. Jack::fetch(); //use a function

未被装饰的名称(如pail)称为未限定的名称( unqualified name);
包含名称空间的名称(如 Jack::pail)称为限定的名称( qualified name)。

using 声明和 using 编译指令

我们并不希望每次使用名称时都对它进行限定,因此C+提供了两种机制( using声明和 using编译指令)来简化对名称空间中名称的使用。 using声明使特定的标识符可用, using编译指令使整个名称空间可用。
usIng声明由被限定的名称和它前面的关键字 using组成:

  1. using Jill::fetch; //a using declaration

using声明将特定的名称添加到它所属的声明区域中。例如main()中的 using声明Jill:fetch将fetch添加到main()定义的声明区域中。完成该声明后,便可以使用名称 fetch代替Jill:fetch。下面的代码段说明了这几点:

  1. namespace Jill
  2. {
  3. double bucket(double n){};
  4. double fetch;
  5. struct Hill{};
  6. }
  7. char fetch;
  8. int main()
  9. {
  10. using Jill::fetch; //put fetch into local namespace
  11. double fetch; //Error! Already have a local fetch
  12. cin >> fetch; //read a value int Jill::fetch
  13. cin >> ::fetch //read a value into global fetch
  14. }

由于 using声明将名称添加到局部声明区域中,因此这个示例避免了将另一个局部变量也命名为 fetch.另外,和其他局部变量一样, fetch也将覆盖同名的全局变量。
在函数的外面使用 using声明时,将把名称添加到全局名称空间中:

  1. void other();
  2. namespace Jill
  3. {
  4. double bucketdouble n){}
  5. double fetch;
  6. struct Hill{}
  7. }
  8. using Jill::fetch: // put fetch into global namespace
  9. int main()
  10. {
  11. cin>>fetch; //read a value into Jill::fetch
  12. other()
  13. }
  14. void other ()
  15. {
  16. cout << fetch; // display Jill:fetch
  17. }

using声明使一个名称可用,而 using编译指令使所有的名称都可用。uing编译指令由名称空间名和它前面的关键字 using namespace组成,它使名称空间中的所有名称都可用,而不需要使用作用域解析运算符:

  1. using namespace Jack; ///make all the names in Jack available

在全局声明区域中使用 using编译指令,将使该名称空间的名称全局可用。这种情况已出现过多次:

  1. #include <iostream> //place names in namespace std
  2. using namespace std; //make names acalable globally

在函数中使用 using编译指令,将使其中的名称在该函数中可用,下面是一个例子:

  1. int main()
  2. {
  3. using namespace jacl; //make names avalable in vorn()
  4. }

在本书前面中,经常将这种格式用于名称空间std有关 using编译指令和 using声明,需要记住的一点是,它们增加了名称冲突的可能性。也就是说,如果有名称空间jack和jill,并在代码中使用作用域解析运算符,则不会存在二义性:

  1. jack::pal = 3;
  2. jill ::pal =10;

变量jack:pal和 jill:pal是不同的标识符,表示不同的内存单元。然而,如果使用usig声明,情况将发生变化

  1. using jack::pai;
  2. using jill:pal
  3. pa1=4; // which one? now have a conflict

事实上,编译器不允许您同时使用上述两个 using声明,因为这将导致二义性。

using 编译指令和 using 声明之比较