c++命名空间总结

目录

一 命名空间来源以及普通命名空间使用

二 命名空间中成员的访问

三 嵌套命名空间

四 同名命名空间

五  c++的头文件都没有后缀.h原因?

六   c++包含了头文件,为什么还要展开命名空间?

七.不包含头文件,用了库里的标识符名会如何?


   一 命名空间来源以及普通命名空间使用

    随着学习终于到了c嘎嘎,开始学的几天确实有许多点没领悟到位,反复回顾才觉得没太多遗漏,现在我就分享一些我的感悟,一开始学的c++的知识都是一些对于c语言不足的方面进行的改进,比如命名冲突的问题,每个人变量,函数的命名都是只顾自己的,不可能每写一个函数,去查一下项目组里有没有人用过这个名字,在这种情况下非常容易造成命名冲突,所以c++就设计出了命名空间,命名空间就像是一个域一样,将自己的变量和函数与其它的独立开来,域这个概念其实c语言是有的,比如局部域和全局域,当局部域和全局域冲突时,局部域优先。接下来我们就用实例子分析命名空间。

#include<iostream>
using std::cout;
using std::endl;//只将常用的展开,展开全部会有命名冲突的风险
namespace num
{
	int a = 2;
}
int a = 3;//全局变量
int main()
{
	//命名空间尝试
	int a = 1;//局部变量

域作用限定符::前加上命名空间的名字,表示到该命名空间去找变量a
	cout << "指定命名空间查找:" << num::a << endl;

如果域作用限定符前未加命名空间的名字,则默认到全局域去找
	cout << "不指定命名空间查找:" << ::a << endl;

不带域作用限定符时,则在默认先到局部域找,再去全局域,默认不会到命名空间域找
	cout << "不带域作用限定符:" <<a << endl;
	return 0;
}

输出结果如图 

二 由此我们可以大致理解命名空间中成员的访问规则

1:展开整个命名空间,使得命名空间内函数暴露在全局域,当然既然是暴露在全局域,遵循一个域内不能同名的规则,

注意:展开整个命名空间会有一定风险,如果我们之后写了一个函数,如果这个和库里的函数命名冲突,但当时我们并没有包含对应的头文件,一旦之后包含了就会出现冲突,至于为什么一包含头文件就会冲突,我在第五点“c++包含了头文件,为什么还要展开命名空间”会详细提及。

2:使用时用域名限定符指定访问的域,在域名限定符前加上命名空间的名字,表示从该空间找,如果未加名字,默认到全局域找,然后到局部域找。

3.展开对应的命名空间成员

三 嵌套命名空间

当一个命名空间包含的变量和函数多了也有可能会出现冲突,所以我们还可以在命名空间再设一个命名空间,嵌套命名空间,接下来就用代码实现一下

namespace num2
{
	int b = 3;
	namespace num3
	{
		int b = 4;
	}
}	
int main()
{

	//嵌套命名空间尝试
	cout << "嵌套命名空间去内层找数字b的结果为" << num2::num3::b << endl;
	cout << "嵌套命名空间去外层找数字b的结果为" << num2::b << endl;
	return 0;
}

结果如下

四 同名命名空间

对于同名命名空间,语法规定是将其归为同一个命名空间,无论是在同一文件还是在不同文件。

五  c++的头文件都没有后缀.h原因?

   我在入门c++的时候,发现c++的头文件都没有后缀.h首先我认为是为了区分c的头文件和c++的头文件,因为c++的标准库都在std这个命名空间内,当别人看到你包含的头文件没有后缀.h时就知道这是c++的头文件,就会意识到使用对应函数要展开命名空间,这样编译器才会去命名空间找,至于为什么c++的库在命名空间呢?因为c++STL库比c++晚了七年才推出,而此时c++程序员已经定义了许多的变量和函数,而这些已经定义的变量和函数名称可能就和STL库冲突,那之后使用这个库的时候就会出现冲突,程序员修改起来太麻烦,所以委员会决定把STL库放进std这个命名空间,为了统一,总不能一部分头文件在命名空间,一部分又不在命名空间,那使用者就要区分哪些库在命名空间,使用时要展开,哪些库不在,使用时不用展开,也很麻烦,所以都丢到命名空间std内。

六   c++包含了头文件,为什么还要展开命名空间?

我在使用c++函数的时候发现包含头文件和展开命名空间总是成对出现,我十分困惑,查阅了许多资料,得出如下推导。

//#include<iostream>
//#include<cstdlib>
using namespace std;
int main()
{
	int rand = 0;
	cout <<rand<< endl;

	return 0;
}

     我认为是因为c++包含头文件是把函数声明和定义包含到源文件,包含的头文件如果是属于std部分的,拷贝到源文件的时候会在该内容外层又封一个namespace std,而要访问这个命名空间内的内容,就要用到先前访问命名空间成员的规则了,后面展开std也不是在那个包含了c++所有的库的std里找,而是在这个源文件新封的std里找函数定义。那如果没包含头文件,展开命名空间也找不到定义,这就是报错未声明未定义的原因,如果不展开命名空间,编译器也不会到命名空间去找,同样报错(想想也很合理,真正的std库里有那么多东西,在这里面查找多浪费时间,把自己包含的头文件封为新的std,然后在这里找,范围就大大减小了,效率必然会提高)

 以上就能解释为什么只展开命名空间,不包含头文件却报错cout未声明,未定义,同理不展开命名空间,编译器也不会从该命名空间找函数,最后报错应该是类似的。

七.不包含头文件,用了库里的标识符名会如何?

   当我理清了包含头文件和展开命名空间std的关系后,那是不是说明如果我用了一个库里的变量名,然后没包含头文件,这样在第六点提到的伪std就找不到该标识符定义,也就不会冲突,开发编译器的人也不傻,这种潜在风险还是会指出的。

 下面为.cpp源文件

 由于c++兼容c,所以上面会被当成c语言,编译器只会以c语言的要求检查你的代码,导致rand不会被说命名冲突,而只要代码里出现c++代码,那编译器就会以c++标准要求你的代码,我估计编译器会对代码做两重保障,一重是检查第六点中提到的伪std命名空间(命名空间内为我们包含的头文件)里是否有会和自己定义的标识符名发生冲突,第二重是编译器还会去真正的std(里面有c++的所有头文件的命名空间)去检查是否会和代码使用的标识符冲突,这样才体现c++语法的严格。

下面是.c源文件,编译器对c语言管的比较宽松,没有上面的第二重要求,所以下面代码能编译通过。

#include<stdio.h>
int rand = 0;
int main()
{
	printf("%d", rand);

	return 0;
}

这里涉及到的一些知识点本人也是查阅一些资料得知,能解释当前状况就停止探究了,还未深入理解编译器的原理,如有错误,可以私信交流讨论。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小何只露尖尖角

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

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

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

打赏作者

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

抵扣说明:

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

余额充值