命名空间

1.C++的作用域

C++中有四种作用域,在不同的作用域中可以定义名字相同的变量,互不干扰。

  • 命名空间作用域:就是程序员利用名字空间定义在C++程序中划分出来的一块比较大的程序区段。在该程序区段内部,可以定义变量、函数、类、typedef、#define 等,最后由{ }包围。名字空间作用域可以跨越多个*.cpp文件而存在。在名字空间作用域内部还可以继续定义其他的名字空间作用域,也就是说,名字空间作用域是可以互相嵌套的。

  • 全局作用域是:C++程序最外层的名字空间作用域,也是最大的名字空间作用域。全局作用域天然存在于C++程序中,它不需要由程序员人为地定义。在全局作用域内部,可以包含其他的,由程序员定义的名字空间作用域,以及没有包含在其他名字空间作用域中的类型,函数,模版,变量。在全局作用域中定义的变量是全局变量,在全局作用域中定义的函数是全局函数。

  • 类作用域:在C++程序中,每定义一个类就会引入一个类域。类体所包含的范围就是类域的范围,在类中定义的所有成员都属于该类域。类域位于名字空间作用域内部,该名字空间作用域可能是全局作用域,也可能是用户定义的命名空间空间作用域

  • 局部作用域:每一个函数体内部都是一个局部作用域。该作用域起始于函数体的左花括号“”,结束于函数体的右花括号“”。每一个函数都有一个独立的局部作用域。在局部作用域内定义的变量都是局部变量。

作用域.png

从上图可以看出,在全局作用域中,定义了两个名字空间W和S。名字空间W又分别位于两个CPP文件A和B中。由此可见,名字空间作用域是可以跨越CPP文件的。在名字空间S中,除了定义了类型外,又定义了一个名字空间E,所以说,名字空间之间是可以互相嵌套的。另外,在名字空间中可以定义类,函数,变量,模版等。

在全局作用域中,除了定义的名字空间W和S外,又定义了一个类D,以及全局函数,全局变量和模版。在类D中,定义了一些成员函数,因此引出了局部作用域。在局部作用域中,如果存在控制语句,就会存在语句作用域。

2.namespace的使用方法

有如下用法:
namespace : 主要的功能是用来解决命名冲突。
1、namespace下面可以放函数、变量、结构体、类。
2、namespace可以嵌套使用
3、namespace必须定义在全局作用域下
4、namespace是开放的,可以随时向namespace中添加内容
5、匿名namespace相当于static修饰

  • 作用域符(::)的使用
1
2
3
global scope(全局作用域符),用法(::scope)
class scope(类作用域符),用法(scope::m_name)
namespace scope(命名空间作用域符),用法(scope::name)
  • 使用命名空间内部成员的方法

在引用命名空间成员时,要用命名空间名和作用域分辨符 对命名空间成员进行限定,以区别不同的命名空间中的同名标识符。即 命名空间名::命名空间成员名 
c++提供了一些机制,能简化使用命名空间的使用:

1.使用命名空间别名

1
2
3
4
可以为命名空间起一个别名,用来替代较长的命名空间名,如:
namespace PeopleA
可以用一个较短的别名替代它。如:
namespace PA = PeopleA

2.使用using命名空间成员名

1
2
3
4
5
using后面的命名空间成员名必须是由命名空间限定的名字,如:
using AA::Cat;
/*如果Cat是一个类,后面就看也直接 Cat m1();这样构造了,不用加作用域了
它的意思是,using 声明以后的程序中如果出现了未指明命名空间的 Cat,
就使用 AA::Cat;但是若要使用BB定义的 Cat,仍然需要 BB::Cat。*/

3.使用using namespace命名空间名

1
2
3
如:using namespace AA;
/*声明了在本作用域中要用到命名空间AA中的成员,
在使用该命名空间的任何成员时都不必再使用命名空间限定。*/
  • 匿名命名空间
1
2
3
4
5
6
7
namespace 
{
void fun()
{
//....
}
}

由于命名空间没有名字,在其他文件中显然无法引用,它只在本文件的作用域有效。若无名命名空间的成员fun函数的作用域为文件A,在文件A中使用无名命名空间的成员,不用也无法用命名空间名限定。