【我的C语言学习进阶之旅】什么是.hpp文件?
目录
- 一、 `.hpp`文件是啥?
- 2.1 .hpp的疑问来源
- 2.2 什么是hpp文件?
- 2.2.1 以往套路
- 2.2.2 .hpp 新方式
- 2.3 使用`.hpp`文件有什么好处?
- 三、思考一下为什么有了.h和.cpp还要.hpp呢?
- 3.1 说一说.cpp
- 3.2 说一说.h
- 3.2 既然可以直接写cpp,为什么还要写hpp?
- 四、扩展阅读
一、 .hpp
文件是啥?
2.1 .hpp的疑问来源
最近在学习OpenGL ES
的时候,学习了一个glm库(https://github.com/g-truc/glm),发现里面的代码包含大量的.hpp文件
当然也有一些是.h文件
好吧,我承认我刚刚学习C++
,对于声明是.hpp
文件不懂。
我的第一想法是:
.hpp
文件 是不是.h
文件 和.cpp
文件的结合?
打开一个.hpp文件内容查看一些,发现有点像我理解的。
下面来正式介绍一下声明是.hpp文件?
2.2 什么是hpp文件?
2.2.1 以往套路
以往在编写 C++
程序时,我们一般分成下面两个部分:
- 编写一个
.h
文件,在里面放上函数的声明
, - 再编写一个
.cpp
文件,在里面添加函数的相关实现
这样在使用的时候包含头文件,再把 .cpp 加到当前工程下编译即可,但是如果此时 .cpp 忘记添加到当前工程下编译,就会出现函数找不到的情况。
如果你的 .h 是模板类的声明,.cpp 是模板类函数的实现,由于模板两次编译的机制,直接包含头文件就出现找不到函数的情况了,这种情况需要把实现和声明放在一起,才能找到函数的定义。
2.2.2 .hpp 新方式
hpp
是 Header Plus Plus
的简写,顾名思义就是 .h
文件加上.cpp
,与*.h
类似,.hpp
也是C++
程序头文件。
本质上就是 .cpp 实现代码混入 .h 文件当中,定义和实现都包含在同一个文件里。
这样调用者只需要include
该.hpp
文件即可,无需再 将.cpp
加入到工程中进行编译。
而实现代码将直接编译到调用者的obj
文件中,不再生成单独的obj
,
采用.hpp
将大幅度减少调用工程中的.cpp
文件数与编译次数,也不用再发布烦人的lib
与dll
,
因此非常适合用来编写公用的开源库,比如开头说的glm
库。
不过 *.h
里面可以有using namespace std
,而*.hpp
里则无。
2.3 使用.hpp
文件有什么好处?
一般来说,
*.h
里面只有声明,没有实现。而.hpp
文件将定义和实现放在同一个文件,这样可以减少了.cpp
文件的数量。无需再将
. cpp
加入到项目中进行编译,将代码直接编译到调用者的obj
文件,不再生成单独的obj
,大幅度减少编译次数,也不用再发布烦人的lib
与dll
,非常适合编写开源库,比如开头说的glm
库。glm
库大量使用模板,采样.hpp
的形式可以保持与各个编译器更好的兼容性(C++ 模板不能把源文件和声明文件分开成两个文件)
三、思考一下为什么有了.h和.cpp还要.hpp呢?
下面内容摘自: C++中.cpp和.hpp的区别
3.1 说一说.cpp
我们可以将所有东西都放在一个.cpp
文件内,编译器会将这个.cpp
编译成.obj
,即编译单元
。
一个程序可以由一个编译单元组成,也可以由多个编译单元组成。
一个.cpp
对应一个.obj
,然后将所有的.obj
链接起来(通过一个叫链接器的程序),组成一个.exe
,即程序
。
如果一个.cpp要用到另一个.cpp定义的函数怎么办?
只需在这个.cpp中写上它的函数声明,链接器将所有的obj链接起来。
但是如果碰巧有相同的函数或外部变量怎么办?
C++可以通过一种叫做链接属性的关键字来限定,某个函数是属于整个程序公用的,还是只在一个编译单元obj
里面使用,这些关键字就是extern
(外部链接)和static
(内部链接)。
3.2 说一说.h
让我们说说.h
。其实没有.h
,程序也能很好的工作,
但是当你发现一个外部链接的函数或外部变量,需要许多分声明,
因为只要使用到该函数的单元,就必须写一份声明在那个.cpp
里面,如果要修改会很麻烦!!!
.h
就是为了解决这个问题而诞生的,它包含了这些公共的东西,然后所有需要使用该函数的.cpp
,只需要用#include
包含进去便可,以后需要修改,只是修改一份内容。#include
并不是什么申请指令,只是将指定文件的内容,原封不动的拷贝进来。
不是很严格的讲,.h
文件做的是类的声明,包括类成员的定义和函数的声明,而.cpp
文件做的类成员函数的具体实现(定义)。
一个*.h
文件和*.cpp
文件一般是配对的。
在*.cpp
文件的第一行一般也是#include "xxx.h"
文件,其实也相当于把xxx.h文
件里的东西复制到*.cpp
文件的开头。
所以,你全部写在*.cpp
文件其实也是一样的。
3.2 既然可以直接写cpp,为什么还要写hpp?
既然可以直接写cpp,为什么还要写hpp?
除了编程规范外,还涉及到类一个重要性质,就是封装性。
比如现在我们公司和另一家软件公司合作,这样就必然要互相提供一些软件的信息(比如一些类,它到底是要做什么的),可是在提供这些信息的同时我们又不像让对方知道我们这些类的具体实现,毕竟这些是我们公司的算法核心和心血啊。
所以这个时候就可以把类的接口(这个类是要做什么的)放在*.h
文件中,而具体类的实现放在 .cpp
文件。这时候我们只要给对方公司.h
文件就行了。这样既提供了必要的信息,又保护了我们的核心代码。
- 最表面的机制是:头文件是程序的界面(是代码界面),提供给程序员以 类、模版、函数等一系列的声明,让程序员知道应该怎么调用里面的“东西”。
- 从动态链接库的角度看:头文件提供界面,使得程序员在需要加载一个库函数的时候(这里也仅仅是举简单的例子)查看头文件就知道怎么加载这个动态库内部的函数。
- 从软件的扩展来说:将头文件作为界面,再去定义它的实现,这样只要保证界面不变(头文件不变),就可以只修改实现文件,而不必修改其他的实现代码。比如你有一个
sort()
函数来排序,在一个大程序中,你后来发现这个sort()
有更好的算法,于是你只需要去修改函数的实现(修改.cpp
文件的sort()
函数的代码),其他使用这个函数的地方可以完全保持不变,这是分割技术的第一个好处 - 从编译的角度看:所有源文件都是被编译器分别划分单元来分别编译,在编译的过程中,头文件被嵌入到实现文件里面一起作为一个编译单元被编译(实现文件
filename.cpp
里的#include "filename.h"
这一行被替换成filename.h
里面的所有内容(实际上会把预处理指令去掉,这才是预处理最本质的作用))。
四、扩展阅读
- C++中.cpp和.hpp的区别
- hpp头文件与h头文件的区别
【我的C语言学习进阶之旅】什么是.hpp文件?相关推荐
- 【我的C语言学习进阶之旅】介绍一下NDK开发中关于JNI函数的两种注册方式:静态注册和动态注册
目录 一.要介绍本篇博客的原因 二.静态注册 2.1 实现原理 2.2 实现过程 2.3 弊端 2.4 示例 三.动态注册 3.1 实现原理 3.2 实现过程 3.3 优点 3.4 示例 一.要介绍本 ...
- 【我的C/C++语言学习进阶之旅】NDK开发之解决错误:signal 5 (SIGTRAP), code 1 (TRAP_BRKPT), fault addr 0xXXX
一.错误描述 今天在使用C++实现一个OpenGL特效的时候,运行出错,如下所示: 错误描述为: signal 5 (SIGTRAP), code 1 (TRAP_BRKPT), fault addr ...
- 【我的C语言学习进阶之旅】解决 Visual Studio 2019 报错:错误 C4996 ‘fscanf‘: This function or variable may be unsafe.
一.问题描述 今天在Visual Studio 2019中写一段C语言的代码,发生生成错误.弹框如下: 点击[否(N)],提示如下: 错误具体信息为: 错误 C4996 'fscanf': This ...
- 【我的OpenGL学习进阶之旅】C++如何加载TGA文件?
一.TGA文件相关介绍 通过前面的博客 [我的OpenGL学习进阶之旅]什么是TGA文件以及如何打开TGA文件? 地址:https://ouyangpeng.blog.csdn.net/article ...
- 【我的OpenGL学习进阶之旅】【持续更新】关于学习OpenGL的一些资料
目录 一.相关书籍 OpenGL 方面 C方面 NDK 线性代数 二.相关博客 2.0 一些比较官方的链接 2.1 OpenGL着色器语言相关 2.2 [[yfan]](https://segment ...
- 【我的OpenGL学习进阶之旅】OpenGL ES 3.0新功能
目录 1.1 纹理 1.2 着色器 1.3 几何形状 1.4 缓冲区对象 1.5 帧缓冲区 OpenGL ES 2.0 开创了手持设备可编程着色器的时代,在驱动大量设备的游戏.应用程序和用户接口中获得 ...
- 【我的OpenGL学习进阶之旅】着色器和程序(上)------着色器
着色器和程序 一.前言 二.着色器和程序 2.1 创建和编译一个着色器 2.1.1 创建着色器 2.1.2 删除着色器 2.1.3 提供着色器源代码 2.1.4 编译色器 2.1.4 查询有关着色器对 ...
- 【我的OpenGL学习进阶之旅】介绍一下 绘制图元
目录 一.绘制图元 1.1 `glDrawArrays` 1.1.1 `glDrawArrays`API说明 1.1.2 `glDrawArrays`API示例 1.2 `glDrawElements ...
- 【我的Android进阶之旅】Android 混淆文件资源分类整理之二:将混淆文件拆分成更小粒度的混淆文件
在我2017年的文章[我的Android进阶之旅]Android 混淆文件资源分类整理中,我已经提及过. 之前将所有的混淆都配置在一个 proguard-rules.pro 这个Android Stu ...
最新文章
- mysql导出数据到txt太慢_分享:mysql导出数据到txt文件
- Linux软件安装管理 - CentOS (二) ---- yum在线安装
- Centos7将firewall替换成iptables
- [解析]多线程加锁Lock调用python2
- android扑克发牌动画,JS实现纸牌发牌动画
- Linux下配置DNS服务器之一--Master服务器
- es6--set数组去重,Map数据结构
- 四个人过桥的题目_云南的几种“勾魂”特产,舌尖上的美味,让人回味无穷,你吃过吗...
- 使用vim的重不重要_VIM高级操作,经常用vim的应该多学习。多开发效率很有大帮助!...
- 【精彩实况】第三届大数据科学与工程国际会议
- iptables命令结构之目标
- c++ 文件读写(转)
- 记录——《C Primer Plus (第五版)》第十二章编程练习第1-8题
- R语言访问mysql和posqlgresql
- IP地址聚合-路由汇聚_共同前缀(1.相似部分2.最后一组二进制比较,取相同,算位数3.转十进制,加位数)
- python爬取电子病历_利用 BERT 模型解析电子病历
- MVP+RecylerView显示数据
- oracle dbms_utility,dbms_utility的两个有用方法
- Excel中的Countif和Countifs
- 2021年东方市铁路中学高考成绩查询,东方2021多少分可以上高中 分数线预测
热门文章
- BBdoc文件管理助手V1.24升级通知 详见官网:http://www.bbdoc.cn
- Revit二次开发相关软件安装资源
- AJAX教程美食滤镜,Python爬虫实例——爬取美团美食数据
- python朗读网页-手把手教你用 Python 来朗读网页
- Ubuntu 9.10 下OpenJDK、SUN JAVA环境及中文字体相关问题
- python 几何教学_python gdal教程之:几何形状geometry与投影projection
- Linux:sshpass和scp的使用
- js 小数取整,js 小数向上取整,js小数向下取整
- SQL的一对多,多对一,一对一,多对多什么意思?
- 化腐朽为神奇,化神奇为腐朽—让人无奈的耳朵的适应性