【C++】namespace 命名空间

灰太狼 2023-09-25 21:06 211阅读 0赞

名称空间

两个术语:

  • 声明区域:声明区域是可以在其中进行声明的区域。
  • 潜在作用域:变量的潜在作用域从声明点开始,到其声明区域的结尾。因此潜在作用域比声明区域小,这是由于变量必须定义后才能使用。

    namespace Jack{}

名称空间可以是全局的,也可以位于另一个名称空间中,但不能位于代码块中。因此,在默认情况下,在名称空间中声明的名称的链接性为外部的(除非它引用了常量)。除了用户定义的名称空间外,还存在另一个名称空间——全局名称空间(global namespace)。它对应于文件级声明区域,因此前面所说的全局变量现在被描述为位于全局名称空间中。

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

using声明和using编译指令

using声明使特定的标识符可用,using编译指令使整个名称空间可用。

using声明由被限定的名称和它前面的关键字using组成:

  1. using Jill::fetch;//使用了这条语句后就可以用fetch代替Jill::fetch.
  2. using namespace Jill;//using声明使一个名称可用,而using编译指令使所有的名称都可用,
  3. //但是它们的使用增加了名称冲突的可能性。

使用using编译指令导入一个名称空间中所有的名称与使用多个using声明是不一样的,而更像是大量使用作用域解析运算符。使用using声明时,就好像声明了相应的名称一样。如果某个名称已经在函数中声明了,则不能用using声明导入相同的名称。然而,使用using编译指令时,将进行名称解析,就像在包含using声明和名称空间本身的最小声明区域中声明了名称一样。在下面的示例中,名称空间为全局的。如果使用using编译指令导入一个已经在函数中声明的名称,则局部名称将隐藏名称空间名,就像隐藏同名的全局变量一样。不过仍可以像下面的示例中那样使用作用域解析运算符:

  1. namespace Jill{
  2. double bucket;
  3. double fetch;
  4. struct hill{};
  5. }
  6. char fetch;
  7. int main(){
  8. using namespace Jill;
  9. Hill Thrill;//可以,建立Jill::Hill
  10. double watch = bucket(2);//use Jill::bucket;
  11. double fetch;//not an error,hides jill::fetch
  12. cin>>fetch;//local fetch
  13. cin>>::fetch;//global fetch
  14. cin>>Jill::fetch;//Jill::fetch
  15. }
  16. int foom(){
  17. Hill top;//不行
  18. Jill::Hill cerat;//可以
  19. }

假设名称空间和声明区域定义了相同的名称。如果试图使用using声明将名称空间的名称导入该声明区域,则这两个名称会发生冲突,从而出错。如果使用using编译指令将该名称空间的名称导入该声明区域,则局部版本将隐藏名称空间版本。

一般说来,使用using声明比使用using编译指令更安全,这是由于它只导入指定的名称。如果该名称与局部名称发生冲突,编译器将发出指示。using编译指令导入所有名称,包括可能并不需要的名称。如果与局部名称发生冲突,则局部名称将覆盖名称空间版本,而编译器并不会发出警告。

可以给名称空间创建别名:

  1. namespace my_vary_favorite_things{...};
  2. namespace mvft = my_vary_favorite_things;

匿名命名空间

  1. namespace{
  2. int ice;
  3. int bandycoot;
  4. }

在该名称空间中声明的名称的潜在作用域为:从声明点到该声明区域末尾。从这个方面看,它们与全局变量相似。然而,由于这种名称空间没有名称,因此不能显式地使用using编译指令或using声明来使它在其他位置都可用。具体地说,不能在未命名名称空间所属文件之外的其他文件中,使用该名称空间中的名称。这提供了链接性为内部的静态变量的替代品。例如:

  1. static int counts;
  2. int other();
  3. int main(){
  4. ...
  5. }
  6. int other(){
  7. ...
  8. }
  9. 采用命名空间的方法如下:
  10. namespace{
  11. int counts;
  12. }
  13. int other();
  14. int main(){
  15. ...
  16. }
  17. int other(){
  18. ...
  19. }

名称空间及其前途

  • 使用在已命名的名称空间中声明的变量,而不是使用外部全局变量。
  • 使用在已命名的名称空间中声明的变量,而不是使用静态全局变量。
  • 如果开发了一个函数库或类库,将其放在一个名称空间中。事实上,C++当前提倡将标准函数库放在名称空间std中,这种做法扩展到了来自C语言中的函数。例如,头文件math.h是与C语言兼容的,没有使用名称空间,但C++头文件cmath应将各种数学库函数放在名称空间std中。实际上,并非所有的编译器都完成了这种过渡。
  • 仅将编译指令using作为一种将旧代码转换为使用名称空间的权宜之计。
  • 不要在头文件中使用using编译指令。首先,这样做掩盖了要让哪些名称可用;另外,包含头文件的顺序可能影响程序的行为。如果非要使用编译指令using,应将其放在所有预处理器编译指令#include之后。
  • 导入名称时,首选使用作用域解析运算符或using声明的方法。
  • 对于using声明,首选将其作用域设置为局部而不是全局。

    include

    using namespace std;//相当于下列代码

    include

发表评论

表情:
评论列表 (有 0 条评论,211人围观)

还没有评论,来说两句吧...

相关阅读

    相关 C++命名空间

    概述       在C语言中程序的全局变量作用域只有一个,所有的全局标识符都共享同一个作用域,在多人开发的时候,容易造成标识符冲突。C++为了解决这个问题提出了命名空间这

    相关 命名空间

    一、为什么使用命名空间 一个大型的工程往往是由若干个人独立完成的,不同的人分别完成不同的部分,最后再组合成一个完整的程序。由于各个头文件是由不同的人设计的,有可能在不同的头

    相关 C++命名空间

    本讲基本要求      \ 掌握:命名空间的作用及定义;如何使用命名空间。      \ 了解:使用早期的函数库  重点、难点      ◆命名空间的作用及定义;

    相关 php命名空间

    php命名空间在php5.3.0中引入,是一个很重要的工具,其作用是按照一种虚拟的层次结构组织php代码,这种层次结构类似操作系统的文件系统目录结构。 命名空间声明语句应该放

    相关 命名空间

    命名空间是 Linux 内核一个强大的特性。每个容器都有自己单独的命名空间,运行在其中的应用都像是在独立的操作系统中运行一样。命名空间保证了容器之间彼此互不影响。

    相关 内核命名空间

    Docker 容器和 LXC 容器很相似,所提供的安全特性也差不多。当用 docker run 启动一个容器时,在后台 Docker 为容器创建了一个独立的命名空间和控制...