hello,大家好啊!经过C语言和简单数据结构的学习,博主终于能开始学习C++了,激动之心溢于言表。
然而刚开始学习,博主就吃了一个闭门羹。为什么C++编程时几乎每次都要敲上using namespace std;这行代码?问了很多人,得到的答案都是别管为什么,加上就完事了,搞得我真的是一阵无语,带着强烈的好奇心,博主通过科技的力量终于搞懂了为什么,下面整理知识点和大家分享。
文章目录
🍀1.命名冲突
大家请看下面这种情况:
为什么一旦包上stdlib.h头文件,程序就报错了呢?
熟悉C语言的同学肯定发现了,在此库中C语言有一个库函数也叫rand,这就导致了命名冲突的问题。
我们说我们定义变量不能用关键字,但是我们能不能用库里面函数的名称呢?貌似没说呀,而且我咋知道你库函数都取了哪些名字。也有这样一种情况,就是在我们与别人合作时,我们俩定义变量或函数时用了同样的名字,在我这里可能是变量,在他那就是函数名。不一定说和库里面进行冲突,项目和项目之间也会冲突。C语言没有解决这个问题,只能有一方让步,改名字。代码量小好说,代码量大了怎么办,谁都不想让步,难道剪刀石头布吗?
💐2.命名空间
💓2.1 命名空间定义
在C/C++中,变量、函数和后面要学到的类都是大量存在的,这些变量、函数和类的名称都将存在于全局作用域中,可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或名字污染,namespace关键字的出现就是针对这种问题的。
🍑2.1.1普通的命名空间
C语言没有很好的解决命名冲突这个问题,C++引入namespace关键字解决这个问题。
使用方法:namespace+名字(你想叫啥都可以,后面代码我用Yuucho来演示)+{}。
{}中即为命名空间的成员(变量、函数名、类型都可以哦)。
我们发现这里并没有打印命名空间里的rand变量值,而是把库函数rand作为一个函数指针,打印了它的地址。那如果我想访问命名空间里的rand怎么办呢?为什么这个时候就没有产生命名冲突呢?我们学习C语言时知道在同一个作用域不能定义同名的变量,现在我们暂且可以认为命名空间里的成员被隔离起来了,那我们在全局这个作用域去看就没有两个rand了。
这里是不是就是我们说的局部变量优先呀,说明同名变量在不同的作用域是可以存在的。那我们有没有办法可以访问到全局的a?
我们打印时加上这个::
就可以了,printf("%d\n",::a);
::
这个叫域作用限定符,表示a是属于左边的作用域的,空白默认是全局作用域。
那我们怎么访问命名空间域里面的成员呢,聪明的你想必都已经猜出来了吧,废话不多说直接上图。
此外,我们可以有多个命名空间域,里面定义的成员可以同名,再也不用担心命名冲突的问题啦!
🐾2.1.2同名的命名空间会被合并
就算我们用命名空间,可能还是会冲突。假设我们有多个头文件,不同头文件之间采用了同名的命名空间,编译器最后会把它们合并在同一个命名空间中。
可以嵌套命名空间来解决这个问题。
🍁2.1.3命名空间可以嵌套
如果你的项目工程比较大,假设是Shopee(别问为什么是Shopee,菜鸡也有梦想[狗头])内部写了一个库。不同的部门之间也可以通过嵌套命名空间的方式来定义成员名。
访问成员可以用Shopee::data::Node n1;
这种方式一层一层去找。
严格来说定义n1,n2应该这样写:
struct Shopee::data::Node n1;
struct Shopee::cache::Node n2;
C++中struct已经升级为类了,可以不写,什么是类呢?我们后面学了再详细讲解。
注意:一个命名空间就定义了一个新的作用域,命名空间中的所有内容都局限于该命名空间中
注意:命名空间中a、b还是全局变量,命名空间域不影响变量的生命周期。
🍒2.2命名空间使用
💕2.2.1加命名空间名称及作用域限定符
使用命名空间的时候,我们刚刚讲的Shopee::data::Node n1;
一层一层去访问,这种指定的方式是不是很麻烦啊,有没有一种办法我不写Shopee。
🐽2.2.2使用using namespace 将命名空间名称引入
我们可以使用using namespace Shopee;
这条语句引入Shopee定义的成员。
当然我们还可以再引入一层:
注:引入也需要一层一层引入,顺序不能颠倒,自己想一想为什么。
这种情况也是不行的:
因为你直接引入了cache,却没有引入Shopee,导致编译器无法识别。
🍂2.2.3使用using将命名空间中成员引入
🌱3.关于using namespace std;
🍊3.1为什么要加using namespace std;
std是封C++标准库的命名空间,count、endl(下一篇博客会详细介绍)是定义在iostream头文件里的,在std这个命名空间中,如果我们不引入std,编译器是编不过的。
不加std也可以但麻烦一点点:
还是得去指定。
🍉3.2加using namespace std;的风险
using namespace std;把std全部引入,虽然方便使用了,但是存在冲突风险。
假设我想定义一个全局变量cout。
解决方法:
- 不引入std,用指定的方法。
- 引入部分常用的。
🍈4.总结
C++语法细节很多,前期学习时大家一定要有耐心,不可急于求成。就像建房子,地基不稳,大风一刮或者一个小地震,楼就垮了,有什么用是吧。
如果看了本篇博客有收获,请多多点赞支持博主,你们支持才是我不断写博客的动力!