C++语言头文件与命名空间详解

        C++是在C语言的基础上开发的。早期的C++并不完善,没有自己的编译器,也不支持命名空间。早期,在编译C++代码的时候是将其翻译成C语言的代码,再通过C语言的编译器完成编译,此时C++仍然在用C语言的标准库,C语言的头文件仍然有效;此外在C语言库的基础上,C++也开发出了一些属于自己的库,增加了属于自己的头文件,例如:<iostream.h>、<fstream.h>等。和C语言一样,当时的C++的头文件仍然是以 .h 为后缀,它们所包含的类、函数、宏等都是全局范围的。

后来,C++引入了命名空间的概念,计划重新编写自己的库,将类、函数、宏等都统一放入一个命名空间,这个命名空间就叫std,std是standard的缩写,意思是“标准命名空间”。但是这时候已经有了很多的用老式C++开发出来的程序了,它们的代码中并没有使用命名空间,此时如果直接修改C++语言原本的库会导致之前开发出来的程序不能运行;而且大多数程序员也并不愿意花费大量的时间和精力用新的C++标准对已经存在的程序进行重写。因此C++的开发人员保留了原来的库和头文件,它们在C++中可以继续使用,然后再把原来的库复制一份,在此基础上进行修改,把类、函数、宏等放进命名空间std下,就成了新版的C++标准库;因此,C++中其实存在了两份功能相似的库,早期旧版本的C++库和新版本的C++标准库。这样老式的C++程序可以继续使用原来的库,而新开发的程序则可以使用新的C++标准以及新的C++库。

        在复杂的头文件的版本中,为了避免头文件的引入在代码编译阶段出现二义性(出现头文件引入的歧义),新标准的C++ 库对头文件的命名做出了调整,去掉了后缀 .h,所以老式C++的<iostream.h>变成了<iostream>,<fstream.h>变成了<fstream>,等等诸多的头文件的改变。而对于原来的C语言的头文件,也采用了同样的方法,但是还要在每个头文件的名字前添加一个字母c,例如<stdio.h>变成了<cstdio>,<stdlib.h>变成了<cstdlib>,<string.h>变成了<cstring>等等。

        需要注意的是旧版本的C++头文件官方是反对使用的,已经明确声明不再支持。但旧的C头文件仍然可以使用,以保持对C的兼容性。因此个人建议,在开发或学习C++语言的过程中,尽量使用C++官方提倡的新的C++标准,使用C++中的<iostream>和C++中C语言的<cstdio>等格式。需要说明的一点是,对于不带. h的头文件,所有的符号都位于命名空间中,使用时必须声明命名空间std;对于使用带. h的头文件,所有的符号都位于全局作用域,可以不使用命名空间,这也是C++标准所规定的。

        至此,说明白了C++中的头文件的内容,很多小伙伴仍然对命名空间的概念比较模糊,接下来重点说明一下命名空间。在开发一个大型的项目的时候,往往是由多名程序员共同开发,会使用大量的变量和函数,不可避免地会出现变量名或函数名的命名冲突,当每个人负责的模块都单独调试通过之后,全部结合在一起之后可能会出现命名冲突的问题,此时仍然会出现问题,为了解决此类的问题,引入了命名空间的概念。接下来举个例子说明一下。

假如说当张三和李四都参与开发一个网盘管理系统,他们都定义了一个全局变量fd,用来指明当前打开的文件,将他们的代码整合在一起编译时,编译器会提示fd出现重复定义的错误。为了解决这个问题,可以使用命名空间。

namespace ZhangSan    //张三定义的命名空间
{
    FILE *fd = NULL;    //张三定义的fd变量
}

namespace LiSi        //李四定义的命名空间
{
    FILE *fd = NULL;    //李四定义的fd变量
}

此时如果将张三和李四的代码放在一起,在编译阶段就不会出现变量重复定义的问题。在使用的过程中只需要指定哪个命名空间,即可使用该命名空间下的变量。这就是命名空间的作用,为了解决合作开发大型项目中出现变量名、函数名、宏定义等重复定义的问题。

        接下来说明一下命名空间怎么定义,不同的命名空间下同名的变量名、函数名等怎么指定具体使用哪一个。

        在C++中,namespace是一个关键字,用来定义一个命名空间,在命名空间中可以包含变量、函数、类、typedef、#define等,最后由{}包裹,具体格式如下:

namespace name      //namespace是定义命名空间的关键字,name是命名空间的名字
{
    #define        //宏定义
    variables;     //变量
    functions;     //方法(即函数)
    class;         //类
}

在使用变量、函数时,需要指明它所在的命名空间,以上述张三李四中的fd为例:

/*    
       ::是域解析操作符,用来指定要使用的命名空间的,
       符号是两个英文符号冒号,两个冒号中间没有空格
*/ 

//第一种指定方式
ZhangSan::fd = fopen("zhangsan.txt","r");    //使用张三定义的变量
LiSi::fd = fopen("LiSi.txt","r");            //使用李四定义的变量


//第二种指定方式
using namespace ZhangSan::fd;
fd = fopen("ZhangSan.txt","r");
LiSi::fd = fopen("LiSi.txt","r");

/*
    在第二种方式中,使用using关键字来声明了ZhangSan::fd,
    表示接下来的代码中如果出现没有指定命名空间的fd,默认使用
    ZhangSan命名空间下的fd,如果需要使用李四的命名空间下的fd,
    仍然需要使用LiSi::fd的格式指定
*/

//第三种方式
using namespace ZhangSan;
fd = fopen("ZhangSan.txt","r");
LiSi::fd = fopen("LiSi.txt","r");

/*
    使用using不仅可以用来声明使用某个命名空间中的某一个变量,还可以用于声明使用
    某个整体的命名空间,此时声明的命名空间中的所有变量都有上述第二种方式的效果
*/

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

骑猫去洱海

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

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

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

打赏作者

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

抵扣说明:

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

余额充值