C++的特性:命名空间

本文介绍了C++中引入命名空间的背景,用于解决C语言中的命名冲突问题。通过命名空间,可以避免全局变量和函数冲突,以及支持代码模块化。文章详细讲解了命名空间的语法、作用域、展开机制以及合并和嵌套定义的特点。
摘要由CSDN通过智能技术生成

C++的特性:命名空间

在学习C++之前,我们需要先了解C++相对于C增加了一些什么特性,这些新增功能和特性一般都是为了解决C语言的的一些遗留问题或者不合理的地方。

场景引例(命名冲突):

#include <stdio.h>
#include <stdlib.h>
int rand = 10;
// C语言没办法解决类似这样的命名冲突问题,所以C++提出了namespace来解决
int main()
{
printf("%d\n", rand);
return 0;
}
// 编译后后报错:error C2365: “rand”: 重定义;以前的定义是“函数”

运行报错:

在这里插入图片描述

这是因为在stdlib库里rand被用作了rand()函数名,所以在预编译阶段头文件展开后,则与全局变量rand产生了冲突,编译器在编译阶段则报出了重定义错误。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这种问题在C语言里是没什么好的解决办法的,所以早期程序员上班的时候就会带一个锤子去上班,遇到这种命名冲突问题就带着武器去到天台干一架,谁能回来谁就可以使用这个名字。这种解决办法显然是不合理的,所以我们的祖师爷“Bjarne Stroustrup”在C++里增加了命名空间的特性,用来解决这种野蛮的处理问题方式

命名空间:

假设在一个项目里有程序员张三和李四,他们两个共同完成同一个项目的同一个功能模块,他们的编程习惯都很相似,变量的取名也大多相同。毫无疑问,这样会造成命名冲突,但是在C++他们就可以采用命名空间来完美的回避这个问题。

命名空间语法:
namespace <name>{
	int x;
	char c;
	//...
}

放到项目中则是:

#include<iostream>
namespace zs {
	int x;
	char c;
}
namespace ls {
	int x;
	char c;
}
int main() {
	zs::x = 10;//张三的x
	ls::x = 20;//李四的x
	printf("张三的x=%d\n", zs::x);
	printf("李四的x=%d\n", ls::x);
}

运行结果:

在这里插入图片描述

命名空间特性的拆解:

首先认识一个符号 ::(域作用限定符)他用来声明使用那个命名空间的变量或者函数

域的概念:

​ 我们知道全局变量和局部变量的区别,假设有全局变量x和局部变量x我们在局部变量的生命周期内优先使用的就是局部变量x,若在局部变量没找到x则会去全局搜索变量x,若找到了则通过编译,若没找到则报错。

​ 我们的命名空间也是如此,在使用的时候默认在局部域先搜索变量,若没有则去全局搜索。但是在代码里我们可以指定直接去那个域找这个变量。这就是**:😗*的作用,如上边张三和李四的例子,变量在被域限定符限定后则不会再在局部和全局域找变量,直接去指定的命名空间找变量来使用。

域的展开:

设想一下,我们所有的变量都定义在命名空间,但是这个项目并不大,只是我们自己的手头练习罢了,基本不会出现明明冲突的可能性,但是每次使用都要加上::来限定是不是特别的麻烦呢,所以我们还有将命名空间权限展开的功能,这样被展开的域他就是一片公共的权限,每个在局部没搜索到的变量都可以在全局搜索到域内的变量,但是这种做法并不建议在大项目内使用,所以除了全部展开还有部分展开的使用,部分展开在大型项目比较常用。

全展开:

语法:

using namespace <name>;

eg:

#include<iostream>
using namespace std;
namespace zs {
	int x;
	char c;
}
namespace ls {
	int x;
	char c;
}
int main() {
	zs::x = 10;//张三的x
	ls::x = 20;//李四的x
	cout << "张三的x=" << zs::x << endl;
	std::cout << "张三的x=" << zs::x << std::endl;
}

运行结果:

在这里插入图片描述

这里还是需要说明下std这个命名空间是C++标准库的命名空间,比如在使用的控制台输出语句cout,他和printf其实是差不多的,但是cout是定义在std这个命名空间的,所以我们把访问权限放开以后就可以直接用cout,当然下边我也用了添加限定符的方式,其实是一样的。

部分展开:

语法:

using <name>::<val>;

这样便可以把某个空间内的某个值公开,其他的依然不受影响。

命名空间的合并:

若存在两个相同名字的命名空间,在编译时会被合并成一个命名空间

eg:

#include<iostream>
using namespace std;
namespace zs {
	int x;
}
namespace zs {
	char c;
}
int main() {
	zs::x = 10;//张三的x
	cout << "张三的x=" << zs::x << endl;
	std::cout << "张三的x=" << zs::x << std::endl;
}

这种最后就会被合并为一个zs的命名空间,里边有int x 和char c。

命名空间的嵌套定义:

​ eg:

#include<iostream>
using namespace std;
namespace zs {
	int x;
	namespace test {
		int x;
	}
}

int main() {
	zs::x = 10;//张三的x
	zs::test::x = 20;
	cout << "zs::x=" << zs::x << endl;
	std::cout << "zs::test::x=" << zs::test::x << std::endl;
}

运行结果:

在这里插入图片描述

END

  • 21
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

栗悟饭&龟波气功

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值