文章目录

  • 为什么要有namespace?
  • namespace怎么用?
    • 定义语法
      • 嵌套
      • 同名融合
    • 命名空间的使用
      • 方式1
      • 方式2
      • 方式3
        • 域作用限定符
        • 在c++中

为什么要有namespace?

回答这个问题之前,我们先看一下这样一段C语言代码

#include int rand = 1;int main(){printf("%d\n", rand);return 0;}

没有学过C语言的同学,可以把这里的printf("%d\n", rand),看成是c++的cout<<rand<<endl,printf()的头文件。

毫无疑问,输出结果一定是1

那如果再加一个头文件呢?

#include#include int rand = 1;int main(){printf("%d\n", rand);return 0;}

此时再运行,就会看到如下报错:

error C2365: “rand”: 重定义;以前的定义是“函数”

为什么rand重定义了?

内有一个C语言自己的库函数

所以这里就同时存在了int rand;int rand(void)两个同名变量,从而报错。

像这里,跟库里的变量名冲突还好,报错了,我们大不了换个变量名,但公司里一个项目几十人、几百人,很难避免。

C++之所以建立,可以说就是为了解决一些C语言的不足,那堆大佬为了解决命名冲突的问题,就提出了命名空间的概念。

namespace怎么用?

要区分不同的域,我们就要为每个域都定义自己的名字,nemespace这个关键字就是这个作用。

定义语法

namespace N1{//支持变量int a = 1;//支持函数int f(){return 1}//支持结构体/类 struct S{int _s;}}

像这样,namespace,后面跟着命名空间的名字,然后接一对{}即可,{}中放命名空间的成员。

嵌套

命名空间是支持嵌套的。

namespace N2{int a;int f();namespace N3{int b;}}

同名融合

同一个工程中,允许存在多个相同名称的命名空间,编译器最后会把他们合成一个命名空间。

namespace N4{int a;}namespace N4{int b;}

编译器处理之后就会变成这样:

namespace N4{int a;int b;}

所以说,这里的两个N4中当然也就不能有同名的变量了。

融合使命名空间可合并,嵌套又可避免合并之后产生内部冲突,这时把嵌套和融合两条规则加在,一起就可以实现如下操作:

一个公司,所有人都使用公司名、项目模块、个人名,的嵌套式空间命名方式,在合并之后可以避免命名冲突。

命名空间的使用

空间定义好了,那怎么使用呢?

#includenamespace N {int a = 10;int b = 20;}int main(){printf("%d\n", a); // 该语句编译出错,无法识别areturn 0; }

直接访问a肯定是不可以的,必须要有一种突破命名空间域的方式。

一般,根据不同情况,有三种方式可以使用。

方式1

使用using namespace 命名空间名称引入

就像我们平时我们用的那句using namespace std;

这里的std其实就是个命名空间标示符,C++标准库中的函数或者对象都是在命名空间std中定义的。

这里用了这句using namespace std;就相当于直接把它的命名空间的壳拆了,也就是可以直接访问里边的所有函数和对象,如cout、cin、endl……

#includenamespace N {int a = 10;int b = 20;}using namespace N;int main(){printf("%d\n", a); // 正常打印return 0; }

这里使用了using namespace N;将于域中的变量都释放于全局区,也就相当于俩全局变量(注:释放前也是全局变量,只不过受命名空间域的限制)

这种方式虽然最为方便,但危险性也是最高的,不管会不会用到,都会放出来,发生命名冲突的的可能性也更高。

方式2

使用using将命名空间中成员引入

有时我们写using namespace std;也只为了使用cincoutendl,所以我们不妨只将cincoutendl放出来,语法如下:

using std::cin;

using std::cout;

using std::endl;

方式1中的案例,同样也可以用此方法:

using N::b;int main(){printf("%d\n", b);return 0; }

方式3

在使用方式3之前,我们要先看一下域作用限定符的概念:

域作用限定符

其实在c语言阶段其实就已经有这个符号了,而且也是用来解决变量名冲突问题的

#includeint a = 0;int main(){int a = 1;printf("%d\n",a);return 0;}

这段代码会报错吗?

答案是不会,这里的两个a一个是全局变量,一个是局部变量,并不会发生访问冲突,再不做任何操作的条件下,会默认访问局部变量。

如果想访问全局域的那个a,只需要在前面加一个域作用限定符::(俩冒号)

#include using namespace std;int a = 0;int main(){int a = 1;printf("访问局部变量(a):%d\n",a);printf("访问全局变量(::a):%d\n",::a);return 0;}

这段代码的运行运行结果就是:

访问局部变量(a):1

访问全局变量(::a):0

在c++中

还是上面的代码,如果a前面啥也没有,默认访问局部变量;

前面加上::,访问全局变量;

那么在::前面再加一个命名空间名呢?

顺理成章的,第三种访问方式产生了

变量名前加命名空间名称::

#include using namespace std;int main(){cout << 1 << endl;}

就可改成:

#include int main(){std::cout << 1<< std::endl;}

案例2:

#includenamespace N {int a = 10;int b = 20;}int main(){printf("%d\n", N::a); // 正常打印return 0; }