(笔记)什么是命名空间 为什么C++头文件有的要加.h有的不用加.h

引言:


问题:学习过C,然后再学c++的人可能会这么问,我#include<iostream>之后,不就是把头文件拉进来了吗,而cin cout等函数不就是iostream.h里面的函数吗,我使用cin cout时,编译器为什么会说  “Error 未定义标示符”呢?


解决方法:这样写


#include<iostream>
using namespace std;
void main()
{
 
 
 
}

但可能不知道为什么加这句

我刚学C++时也不明白为什么,看课本解释说什么命名空间的,看不明白,只是知道这样写才能通过编译,也没有深究,每次都默默加上去的说。

现在,任然是个菜鸟的说,看了一些资料之后,写了这篇笔记“关于using namespace std;以及为什么有的头文件需要加上.h而有的头文件不需要”,可能不够严谨,欢迎指出错误。


这是个历史问题。


一、从库的概念说起


这得从库的概念说起,你#include进去的就是别人帮你写好的库,你可以直接调用头文件里面封装好的函数或类,比如你用的cin cout等就是c++标准库里面的函数,这样你就不用自己写一个函数cin 来实现输入功能,也不用写函数cout来实现输出功能,直接调用就可以了。除了C++标准库,一些公司封装了一些函数,实现某些强大的功能,然后拿来卖,比如微软的MFC ,Trolltech公司的Qt等,所以c++变得更加强大,不仅可以直接调用标准库,还能调用别的公司封装好的库。


二、命名空间诞生的原因

早期的c++库内容有限,可随着时间的推移,库的功能越来越强大,每个厂商之间可能将库里面的函数或类取了相同的名字,比如说A公司的库就可能定义了一个叫做sum的函数,而B公司也定义一个叫做sum的函数,于是就出现问题了,程序员开发时,如果同时使用了A的库,又使用了B公司的库,那么就可能出现混乱,你调用的sum到底是哪家公司的。最初,人们就想了个办法,厂商将名字取得更长更复杂来避免重复,可这样做却给编写和阅读带来了困难。后来,人们创造了命名空间这个概念(1998年),它能有效地指出某个标示符到底属于哪个库。


三、什么是命名空间

通过使用 namespace xxx;来说明你所用的这个函数或类来自于哪个库或者是自己写的函数。例如,C++标准程序库就把标准库库里面的函数或类的名称放在一个“叫做std的命名空间”,比如cin cout这两个函数的名字就放放在命名空间std里面,你可以通过std::cin  std::cout来说明你这里使用的cin cout是来自标准库里面的函数,而不是自己写了个名字叫做cin的函数,也不是别的厂商的库里面的函数cin,但这样也比较麻烦,每次调用的话就得把cin写成std::cin,如果你想要经常可以在程序的开头使用 using std::cin;来说明以下代码所使用的cin是来自std这个命名空间,也就是标准库里面的函数。若程序需要大量地使用标准库里面的函数,就可以把using namespace std;放在程序的开头,来说明以下代码将使用标准库的函数或类,程序员不能取和标准库里面冲突的函数或类的名称,于是你就能直接使用cin cout而不必用std::cin来说明你这里的cin是std里面的。总之,通过命名空间就能有效的说明某个函数或类到底是调用了属于哪里的库。


四、命名空间的出现导致新版头文件的诞生

可是,这样做带来了一个新的问题,c++发展了那么多年(直到1998年推出命名空间,大约发展了16年),现存的代码已经有一定的量了,你突然给我搞了一个命名空间,以前可没这东西,我以前写的代码就不能再新的编译器下运行了,这可不行。

于是,人们想出了一个办法。为包装了std的那部分标准库构件创建出新头文件名。并且把新的头文件名字取和旧头文件相同,但不加后缀.h。所以<iostream.h>变成了新版头文件<iostream>,<complex.h>变成了<complex>,而新旧头文件的功能基本上相同的(但不完全相同),所以使用<iostream>时,想要调用里面的函数,就得使用类似std::cin的方法来说明cin是使用标准库里面的函数,而不是自己定义或别的厂商的库的函数,当然,如前文所述,也可以在开头使用using namespace std;来说明以下程序将使用标准库的函数。

当使用<iostream.h>时,使用的是全局命名空间,也就是早期的c++实现(c++标准已经明确表示不支持这种用法了,所以理论上来说这种用法是非法的,但编译器厂商有可能还支持这种用法)

当使用<iostream>时,该头文件没有定义全局命名空间,必须使用命名空间 std来说明你所使用的函数或类是来自iostream的

而c++对待C头文件(c++可以使用c的头文件)的方式是继续支持旧的头文件的支持,也既<string.h>这种用法,以保持对C的兼容性。但为了与时俱进(因为命名空间是个好东西呀),任然对应旧版头文件开发了新版的头文件,命名方式是,在每个旧版名字前添加一个c。所以C的头文件<string.h>变成了新版c++的<cstring>,C的头文件<stdio.h>变成了新版c++的<cstdio>。这也是为什么c++代码里面有的头文件加.h,有的不加.h的原因。#include进来可能是(1)、新版C++头文件,如#include<iostream>(2)、新版C语言头文件,如#include<cstring>(3)旧版的C头文件,如#include<string.h> (4)、旧版C++头文件,理论上来C++是不支持这个用法了,但一些编译器厂商任然可以这样使用


五、完结

回到开头的那个问题,#include<iostream>之后,是不能直接调用里面的函数的,因为<iostream>这个头文件属于c++标准库的一部分,既cin这个函数属于标准库的一个函数,如上文所述,它的用法是在函数名字放在了命名空间std中,你得用std::cin来说明一下这里的cin是来自命名空间std里面的,也就是标准库里面的cin函数,而不是别的库的cin函数。这是C++的用法,不要与C混淆。

总结概括:库的爆炸性的发展导致经常出现命名重复,从而提出了命名空间的概念,有效地说明同个名称的函数到底来自哪个库,但这导致过去几年所开发出来的代码可能不能使用,从而C++委员会对应旧版头文件重新开发了新版的头文件,命名方式相同,但不添加后缀.h。委员会对待C语言头文件的方式类似,重新开发了一套头文件,命名方式是在头文件开头加上字母c,并去掉后缀.h.

新版C++对待旧版C++和旧版C语言的方式差别在于,明确提出不再支持C++头文件.h的使用,但任然支持C语言头文件.h的使用。这也是为什么现在的C++代码有的使用了.h,(调用了旧版C语言头文件),也可能不加.h(使用新版头文件)。


参考资料:

http://baike.baidu.com/link?url=2SE8e6O1JE_JReBktYV-19rMH62tnJTJ2hV5NWCRKrWiW5Y3CJ6oDWh6OFGApz5H1ETGatKizyKxlzWzgeDbuq


http://www.kuqin.com/effectivec2e/ch12e.htm













  • 36
    点赞
  • 65
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值