> 文章列表 > 【C++】1. 命名空间

【C++】1. 命名空间

【C++】1. 命名空间

文章目录

  • 一、命名空间的由来
  • 二、命名空间的使用
    • 2.1 关键字:namespace
    • 2.2 访问命名空间里的标识符
    • 2.3 命名空间的特点
  • 三、总结

一、命名空间的由来

当我们使用c语言编写项目时,可能遇到以下情况:

  1. 变量名与某个库函数名重复,导致保错。这种情况一般是自己不知道引用的头文件包含哪些库函数。

【C++】1. 命名空间
2. 和队友一起编写项目时,自己使用的标识符和队友的标识符名字一样,导致代码整合时发生错误。这种情况很难避免,毕竟一些常用的命名习惯是大家都有的,那这个时候怎么办呢?总不能打一架来争夺命名权。
【C++】1. 命名空间
基于这样的问题,c++的创造者创造了命名空间。

当多个库或代码文件被组合在一起时,可能会出现相同名称的变量、函数、类等,这种情况称为“命名冲突”。命名空间可以在不改变原有代码的情况下,将标识符放在特定的作用域中,以避免命名冲突。


二、命名空间的使用

上面提到,命名空间通过将标识符放在特定的作用域来解决命名冲突。这里出现一个名词:作用域。学过c语言的人应该都知道这个概念。

作用域是指在程序代码中,标识符有效的区域或范围。在作用域内,标识符可以被使用或修改,而在其它作用域内则可能无法访问该标识符。

变量只有在它的作用域里才能发挥它的作用。局部变量只能在局部域发挥作用,全局变量只有在全局域才能发挥作用。
由于作用域的存在,请问以下代码会发生命名冲突吗?
【C++】1. 命名空间
不会!因为两个a不在同一个域中。
编译器在使用a这个标识符时,一般按照以下顺序去寻找a:局部域->全局域。


因此我们按照这样的思路,来创建一个命名空间域存放我们设置的标识符。

2.1 关键字:namespace

namespace的使用如下:
【C++】1. 命名空间
此时sfw里的a就不会与sfw域外面的a产生冲突。
命名空间内部可以包含结构体,函数……


2.2 访问命名空间里的标识符

上面提到编译器查找标识符的顺序是 :局部域->全局域。
现在我们创建了sfw这个命名空间,那编译器此时访问顺序会变成什么?不变,因为编译器不会主动去访问命名空间里的内容。
【C++】1. 命名空间
那我们怎么访问命名空间里的标识符呢?有三种方法。

  1. 展开命名空间:通过使用using这个关键字,如下图
    【C++】1. 命名空间
    注意:展开命名空间相当于把这个命名空间暴露在全局域当中。
    这就意味着:如果此时全局域有一个标识符和sfw命名空间里一个标识符相同,则会发生命名冲突。如下图,因此不推荐这种玩法。
    【C++】1. 命名空间
    补:using namespace sfw;需要在sfw这个命名空间创建后才能使用,如果这句代码在namespace sfw {……}上面,则会报错

  1. 使用作用域限定符::来访问命名空间里的标识符 : 命名空间名字+::+标识符,如下图
    【C++】1. 命名空间
    这种方式就不用担心展开命名空间造成的错误了,因此这种方式往往是大型团队项目的使用方式

  1. 展开命名空间的某一部分:using + namespace + 命名空间的名字 + :: + 标识符
    【C++】1. 命名空间
    这种方式仍有展开命名空间相同的错误,比如此时刚好有个全局变量是a,一样也会报错。个人还是推荐第二种方式。

2.3 命名空间的特点

我们已经知道了如何创建和访问命名空间,下面我们来学习命名空间的一些特点。

  1. 命名空间的嵌套:一个命名空间可以包含另一个一个命名空间
    【C++】1. 命名空间

  2. 命名空间的合并
    请问:命名空间会发生命名冲突吗?即我创建了一个命名空间:sfw,你也创建了一个命名空间:sfw。
    答:冲了但也没冲。编译器会将相同名字的命名空间合在一起,如果这两个命名空间都定义了相同的标识符,则发生冲突。
    【C++】1. 命名空间


三、总结

命名空间是C++中用来避免命名冲突的一种机制。创建和使用命名空间的方法如下:

创建命名空间:在全局或其他命名空间的作用域内,使用关键字namespace加上命名空间的名称来创建一个命名空间,例如:

namespace my_namespace {// 命名空间的定义内容
}

命名空间中可以定义变量、函数、类等标识符,并给他们都加上该命名空间的前缀。例如:

namespace my_namespace {int my_var = 0;  // 定义命名空间内的变量void my_function() {  // 定义命名空间内的函数// 函数代码}class MyClass {  // 定义命名空间内的类// 类定义};
}

使用命名空间:在使用命名空间内的标识符时,需要在其前面加上命名空间的名称和作用域限定符(::),例如:

my_namespace::my_var = 100;   // 使用 my_namespace 命名空间内的变量
my_namespace::my_function();  // 调用 my_namespace 命名空间内的函数
my_namespace::MyClass obj;    // 使用 my_namespace 命名空间内的类

可以使用using关键字引入命名空间中的标识符,使得在该作用域内可以直接使用该标识符而不需要加上命名空间前缀。例如:

using my_namespace::my_var;
my_var = 100;   // 直接使用 my_var,无需加上命名空间前缀

命名空间的使用可以避免不同模块或工程中使用同名标识符导致的冲突问题,同时也便于代码维护和阅读。