写这篇文章的原因
就我个人而言,信奥一本通上的代码以及注释中并没有清楚地解释using namespace std的真正含义,同时也没有解释.h头文件和C头文件的区别在何处,而只是把专有名词原封不动地照搬到书上,知识面的层面上不能融会贯通,会对编程学习有影响,因此我对我的疑问进行了查阅,终于在《C++ Primer Plus》找到了我希望得到的解释,我希望不仅是我能明白其中的含义,同时也能够分享给各位OIer。
须要清楚的概念
- 在执行简单程序的main代码区块之前,程序会调用预处理器,然后自动执行#include<···>命令,使代码中的函数及类得以生效。
- 调用的头文件有两种,分别是.h头文件,以及C头文件,一下将对两种头文件进行区分。
.h头文件和C头文件的正确区分方法
当我们需要使用printf输出语句函数时,易知我们需要调用cstdio库,里面储存的是函数相关信息,从教材上可知执行以下代码即可:
#include<cstdio>
using namespace std;
像cstdio这样的文件叫包含文件,也因为他们被包含在其他文件中的起始处,所以也叫头文件。C++编译器自带了很多种头文件,每个头文件都支持一组特定的工具。而在C语言的传统当中,头文件使用的扩展名是.h,用后缀名将其简单地表示为头文件。而在C++中,这些头文件被重命名。不仅去掉了.h的后缀,且文件名前会加上字母c。例如C++版本的stdio.h是cstdio,也就是上文提到使用printf需要调用的类库。而C++中新出现的类库则不需要加上前缀c,例如iostream类库。
那很多人会问其中的区别在何处?仅仅只是名称上的变化吗?
我将从下面一张列表为大家分析其中的奥妙之处。
头文件类型 | 约定 | 示例 | 说明 |
---|---|---|---|
C++旧式风格 | 以.h结尾 | iostream.h | C++程序可以使用 |
C旧式风格 | 以.h结尾 | stdio.h | C/C++程序可以使用 |
C++新式风格 | 没有扩展名 | iostream | C++程序可以使用,使用namespace std |
转换后的C | 加上前缀c,没有扩展名 | cstdio | C++程序可以使用,可以使用不是C的特性,如namespace std |
- C++头文件后缀ANSI/ISO委员会非常纠结该使用哪一种后缀,最后摒弃C语言中繁杂的扩展名,同意不使用任何扩展名。
using namespace std语句的含义
其实不难看出,在经过头文件转换的过程后,头文件的适用范围也变化了。而且在新风格的C++语言中,在进行类库调用后,还需要定义全局命名空间,也就是标题中的using语句了。那么为什么.h头文件调用过程中不需要using语句呢?在此我们将引入新的概念命名空间。
命名空间的概念
命名空间是C++的一项特性,只在使大型程序组合的过程更加容易,亦有助于组织程序。例如一个潜在的问题,两个已经做成的大型程序,他们都包含了printf()函数,使用函数时编辑器将不能识别他们的版本而报错,而命名空间则可以将不同函数版本封装到不同的命名空间中,来指出大型程序的不同函数版本。
例如可以将First Company的程序封装到名为First的命名空间中,Second Company的程序封装到名为Second的命名空间中,在调用函数printf()时,即可使用名称空间来区分不同版本了。
First::printf("Hello World!");
/*使用First Company的printf()函数*/
Second::printf("Hello World!");
/*使用Second Company的printf()函数*/
using函数的真正奥义
按照新式的类库调用,C++编译器中的标准组件,包括类、函数和变量都默认存放在std命名空间,这意味着所有函数前必须加上std::才能正常使用,反之则无法识别函数的命名空间。例如你必须输入std::cout<<"···";才能正常调用cout()函数,为了使代码更简洁,运行效率更高,using命令应运而生,当使用using namespace std时,程序将使用std命名空间中的函数,则再无需添加前缀std::,直接调用函数即可。
当然,这是一种很偷懒的方法,若在大型程序中,只用到std中的几个函数,则可使用using语句直接使函数生效,进一步提高程序运行效率。代码如下:
using std::printf;
using std::scanf;
···
当然对于初学C++的我们来说,只要使用偷懒的方法即可,与复杂的调用过程效率基本无二。
网友评论