写c++项目时,大家常用到的一句话就是:
using namespace std;
怎么具体解析这句话呢?
命名冲突:
在c语言中,我们有变量的命名规范,如果一个变量名或者函数名和某个库里面自带的库函数或者某个关键字重名,就会报错,这时候,我们只能给自己定义的变量或者函数进行改名。
但是,为了填补c语言在这方面的缺陷,c++提供了命名空间这一功能,专门解决命名冲突这一问题。
具体情景:
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
int rand = 0;
int main()
{
printf("%d\n", rand);
return 0;
}
出现这种情况的原因就是,在stdlib这个库里面本身就有一个rand函数,然后和变量发生了命名冲突。
命名空间的语法定义:
namespace xxx
{
int rand = 0;
struct Node
{
struct Node* next;
int val;
};
}
可以看出,在命名空间中,我们可以定义变量、函数、结构类型。
命名空间的具体功能:
当主函数使用某一个变量时,默认从全局找,而不会到命名空间找,也就是说,就像是对外加了一层权限,只有在特定情况下才可以调用。
调用命名空间中的变量:
想要指定调用的变量不是库里的,也不是全局的,而是命名空间里的。我们用到域作用限定符(::)
#include <stdio.h>
#include <stdlib.h>
namespace shunshun
{
int rand = 0;
struct Node
{
struct Node* next;
int val;
};
}
int main()
{
//访问的是库函数的地址
printf("%p\n", rand);
//访问的是我们想访问的rand变量
printf("%d\n", shunshun::rand);//::为域作用限定符
struct shunshun::Node node;//域作用限定符不可以加在struct前面,要加在结构名前面。
return 0;
}
但是,每次这样访问有些麻烦,怎样简化?
展开(授权)功能:
展开又分为全部展开和部分展开。
全部展开是将命名空间中的每个变量的权限解开,可以访问。
部分展开是将命名空间中的部分变量的权限解开。
部分展开:
using shunshun::rand;
意思是,调用rand变量时,默认调的是shunshun这个命名空间里的rand变量。
全部展开:
using namespace shunshun;
这时,命名空间中所有的变量都可以别访问,存在安全风险,所以一般的大型项目是不会全部展开的!
同时我们就可以解释开头的那句话了:
using namespace std;
std是C++的一个标准库,这个标准库里的函数是定义在一块命名空间里的。如果,单纯的通过头文件把库引过来,等到头文件展开时(把头文件里的内容拷贝,替换这行头文件),这个库里的函数是呆在一个命名空间中的,如果,不写这句话(using namespace std;),那么我们就不能用这个标准库的函数。所以,这句话就是为我们使用C++标准库里的函数做准备的。
套娃功能:
这个命名空间是可以嵌套的
namespace shunshun
{
int rand = 0;
struct Node
{
struct Node* next;
int val;
};
namespace lili
{
int love = 720;
}
}
调用时,如果我们想用这里的love变量,就得写两层域作用限定符——shunshun::lili::love。
自动合并功能:
如果,我们定义了两个或多个相同名称的命名空间,这时也不会报错,命名空间是可以自动合并的(这些相同名称的命名空间可以在同一个工程下的不同文件中的),但是如果这些同名的命名空间中定义了相同名称的变量或者函数(比如,两个shunshun命名空间中,都有rand这个变量),那这时就会发生冲突。