在C/C++中,变量,函数和和类这些名称都存在于全局作用域中,可能会导致很多冲突,使用命名空间的目的是对标识符的名称进行本地化,避免命名冲突或名字污染,namespace关键字就是解决这种问题的。如下程序并无问题:
#include<stdio.h>
int rand=0;
int main(){
printf("%d\n",rand);
return 0;
}
但是如果在上述代码中加入一段#include<stdlib.h>,因为stdlib.h头文件里面有一个rand的函数,此时就会出现如下错误:
命名冲突(C语言中没有方法可以解决这个问题):
1.我们写的代码跟库冲突
2.我们互相之间写的代码冲突
这时C++中就有了namespace用来定义一个命名空间,语法:namespace 命名空间名{成员},示例如下:
#include<stdio.h>
#include<stdlib.h>
namespace ThisLocality{
int rand = 0;
}
int main() {
printf("%d\n", rand);
}
这时就解决命名冲突这个问题,命名空间就像一堵墙把rand围起来了,此时的rand默认访问的是全局就是stdlib.h头文件里面的函数rand,而namespace里的rand就不会被访问了,既然是访问函数rand那么就用%p来打印地址,此时代码运行如下:
此时想访问namespace里面rand,只需要在rand前面加,命名空间名::(域作用限定符)变量名就可以了,示例代码如下:
#include<stdio.h>
#include<stdlib.h>
namespace ThisLocality{
int rand = 0;
}
int main() {
printf("%p\n", rand);//访问的是stdlib.h头文件里面的函数
printf("%d\n", ThisLocality::rand);//此时访问的是bit命名空间里的rand变量
}
此外,命名空间除了可以定义变量也可以定义函数,结构体,还可以嵌套,代码如下:
namespace ThisLocality{
//定义变量
int rand=10;
//定义函数
int Add(int left,int right){
return left+right;
}
//定义结构体
struct Node{
struct Node*next;
int val;
};
//嵌套
namespace ThisLocality2{
int rand=100;
}
}
上述几种定义的访问方式如下图:
上述中函数和变量的访问方式只不过就是在名字后面加了()里面放对应的参数,而定义命名空间中的结构体的时候命名空间名是加在结构体名前面的所以是ThisLocality::Node 结构体变量名,最后访问int rand=10;首先要找到命名空间ThisLocality然后再::命名空间名,这是找命名空间里的命名空间最后就到了这个命名空间里了,最后::变量名就可以访问了,我们知道嵌套如果太深也不好一般来说两层基本就够了。
下面在Stack.h中定义了ThisLocality然后在Stack.cpp中完成的ThisLocality里面函数的内容,因为他们是同名所以会自动合并成一个命名空间,所以在Test.cpp中导入Stack.h就可以使用ThisLocality中的函数了。
展开命名空间,使用展开命名空间就像把命名空间里面的代码直接放到展开位置上了,使用了展开命名空间之后就不需要再使用,命名空间::这段了可以直接使用里面的变量或者函数跟普通变量使用方法并无区别。
using namespace 命名空间名;
展开示例:
可以看到展开之后不需要加,命名空间名::,如其中的ST它会先去全局中找没找到就会去声明的命名空间里面找,如果在这两个地方都没有找到就会报错,但是不建议大量使用这种方法。
我们经常会在很多C++的代码中看到:using namespace std;这段代码,这段代码其实是C++官方库里面的命名空间,这里是直接把这个库展开了,这样就可以随便用里面的东西了。C++把东西放在里面,就是因为容易发生冲突,如果展开那不是本末倒置了,但是日常小程序为了方便可以这样做。