命名空间

为什么要使用命名空间?

  - 一个大型的工程往往是由若干个人独立完成的,不同的人分别完成不同的部分,最后再组合成一个完整的程序。由于各个头文件是由不同的人设计的,有可能在不同的头文件中用了相同的名字来命名所定义的类或函数,这样在程序中就会出现名字冲突。
  - 开发者定义的名字有可能会与C++库中名字产生冲突。
  - 注:名字冲突就是在同一个作用域中有两个或多个同名的实体。
  为了解决命名冲突 ,C++中引入了命名空间,所谓命名空间就是一个可以由用户自己定义的作用域,在不同的作用域中可以定义相同名字的变量,互不干扰,系统能够区分它们。

什么是命名空间?

  命名空间又称为名字空间,是程序员命名的内存区域,程序员根据需要指定一些有名字的空间域,把一些全局实体分别存放到各个命名空间中,从而与其他全局实体分隔开。通俗的说,每个名字空间都是一个名字空间域,存放在名字空间域中的全局实体只在本空间域内有效。名字空间对全局实体加以域的限制,从而合理的解决命名冲突。

命名空间的格式

namespace 命名空间的名称
{
  命名空间包含的类型(实体)
  - 变量
  - 常量
  - 函数(定义或声明)
  - 结构体
  - 类
  - 模板
  - 命名空间
} //end of namespace

命名空间的使用方式

using编译指令

#include <iostream>

// std代表标准命名空间
// 如果一个名称空间中有多个实体,使用using编译指令,就会把该空间中的所有实体一次性引入到程序之中
using namespace std;

int main()
{
  cout << "hello world" << endl;
  return 0;
}

作用域限定符::

#include <iostream>

namespace xk
{
  int number = 10;
  void display()
  {
    //cout, endl 均是命名空间std的实体
    std::cout << "xk::display()" << std::endl;
  }
} //end of namespace xk

int main()
{
  //通过 命名空间::实体 来使用命名空间
  std::cout << "xk::number = " << xk::number << std::endl;
  xk::display();  
  return 0;
}

using声明机制

#include <iostream>

//通过using的声明,可以在下面直接使用声明的cout与endl两个实体
using std::cout;
using std::endl;

int main()
{
  cout << "hello world" << endl;
  return 0;
}

三种命名空间使用的比较分析

  - using编译指令
    对于初学者对于命名空间中的实体并不熟悉,直接使用这种方式,可能会出现名字冲突
  - 作用域限定符
    每次使用命名空间中的实体都要加上 :: ,比较冗余
  - using声明机制
    初学者推荐使用,需要使用哪个实体就引入到程序中,不需要的实体就不引入,尽可能的减少犯错误的概率

匿名命名空间

  不定义名字的命名空间称为匿名命名空间。
  由于没有名字,该空间中的实体,其它文件无法引用,它只能在本文件的作用域内有效,它的作用域是从匿名命名空间声明开始到本文件结束。
  在匿名空间中创建的全局变量,具有全局生存期,却只能被本空间内的函数等访问,是static变量的有效替代手段。

命名空间的嵌套及覆盖

#include <iostream>

using std::cout;
using std::endl;

int number = 1;

namespace xk
{
  int number = 10;
  namespace rl
  {
    int number = 100;
    void display()
    {
      cout << "xk::rl::display()" << endl;
    }
  } // end of rl
  
  void display(int number)
  {
    cout << "形参number = " << number << endl;
    cout << "xk命名空间中的number = " << xk::number << endl;
    cout << "rl命名空间中的number = " << xk::rl::number << endl;
    cout << "全局变量number = " << ::number << endl;
  }
} //end of xk

int main()
{
  xk::rl::display();
  xk::display(1000);
  return 0;
}

命名空间的总结

  - 提倡在已命名的名称空间中定义变量,而不是直接定义外部全局变量或者静态全局变量
  - 如果开发了一个函数库或者类库,提倡将其放在一个名称空间中
  - 对于using 声明,首先将其作用域设置为局部而不是全局
  - 不要在头文件中使用using编译指令,这样,使得可用名称变得模糊,容易出现二义性
  - 包含头文件的顺序可能会影响程序的行为,如果非要使用using编译指令,建议放在所有#include预编译指令后。
原文地址:https://www.cnblogs.com/xkyrl/p/14660300.html