C++ 中到底是应该include .h文件还是应该include .cpp文件

这篇具有很好参考价值的文章主要介绍了C++ 中到底是应该include .h文件还是应该include .cpp文件。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

在阅读一个较大的解决方案中,对于其他文件夹下的.h和.cpp文件,有时候#include“XXX.h”文件,有时候是#include“XXX.cpp”文件,而且二者还不能更换。下面就好好分析一下他们二者的区别。
 

测试

测试:XXX.h和XXX.cpp有没有在解决方案里的差别

       如果 .h 文件和 .cpp 文件都已经添加在解决方案里,只要在 main 的头文件中 include 对应的 .h 文件即可。
  如果 .h 文件和 .cpp 文件不在解决方案里,可能在其他文件夹里,单独 include.h 文件就会报错“error LNK2019: 无法解析的外部符号”。

        但是单独 include.cpp 就能运行了,而此时当前 main.cpp 里面有没有对应的 .h 头文件都可以正确运行(因为 .h 文件里有 #pragma once 防止多次定义),

        这个很好解释,include 就是把对应的代码拷贝一份进去,拷贝之后,自定义函数的定义本来就在使用前,有没有头文件的声明都可以。为了验证 include 是不是就是将程序拷贝,做了实验验证。

        在自定义函数使用前 #include“XXX.h” 用于函数的声明(意思是在 main.cpp 最前面 #include“XXX.h),在 main 函数结束之后#include“XXX.cpp”,运行果然正确。
  初步结论:说明当.h文件和.cpp文件不在解决方案里的时候,#include就是纯粹的拷贝复制工作。但是当 .h 和 .cpp 文件在解决方案的情况需要进一步验证。

        同时也说明,.cpp 文件有没有包含进工程文件的情况是不同的。

探究

按照所有查到的信息都说明一点内容:凡是#include的头文件,都是把对应的文件信息拷贝复制一份进来。显然这个笼统的概念是不对的。

  源程序->预处理->编译和优化->生成目标文件->链接->可执行文件
  参考之前我转载的3篇博文C++编译与链接的三部曲(强烈推荐看一看)。大致总结如下:
 

预处理(简单替换)

  预处理做如下工作:

预处理器主要负责以下的几处:
1.宏的替换
2.删除注释
3.处理预处理指令,如#include,#ifdef

编译和优化(高级语言->汇编语言)

词法分析 – 识别单词,确认词类;比如int i;知道int是一个类型,是一个关键字以及判断i的名字是否合法。
语法分析 – 识别短语和句型的语法属性;
语义分析 – 确认单词、短语和句型的语义特征;
代码优化 – 修辞、文本编辑;
代码生成 – 生成译文。
内联函数的替换就发生在这一阶段。
C++ 中到底是应该include .h文件还是应该include .cpp文件

编译的另一个重要方面就是编译单元
  什么是编译单元呢?简单来说一个cpp文件就是一个编译单元。
  在集成式的IDE中,我们往往点击一下运行便可以了,编译的所有工作都交给了IDE去处理,往往忽略了其中的内部流程。
  事实上编译每个编译单元(.cpp)时是相互独立的,即每个cpp文件之间是不知道对方的存在的(不考虑#include “xxx.cpp" 这种奇葩的写法)。
  编译器会分别将每个编译单元(.cpp)进行编译,生成相应的obj文件,然后链接器会将所有的obj文件进行链接,生成最终可执行文件内部链接与外部链接。
  这里能作为单独编译单元的是添加进工程的cpp文件,外部文件夹的cpp文件并不单独成为编译单元。
 

生成目标文件(汇编语言->二进制机器语言)

  汇编过程实际上指把汇编语言代码翻译成目标机器指令的过程。
  在最终的目标文件中,编译器把一个cpp编译为目标文件的时候,除了要在目标文件里写入cpp里包含的数据和代码,还要至少提供3个表:

未解决符号表;
导出符号表;
地址重定向表

未解决符号表提供了所有在该编译单元里引用但是定义并不在本编译单元里的符号及其出现的地址;
  导出符号表提供了本编译单元具有定义,并且愿意提供给其他编译单元使用的符号及其地址。
  地址重定向表提供了本编译单元所有对自身地址的引用的记录。
  这就是不同cpp之间的通讯方式。

C++ 中到底是应该include .h文件还是应该include .cpp文件

从这个定义方式上看,主cpp文件和其他所有cpp文件都是平等的关系,只不过主cpp里面包含了main函数而已,而main函数和其他所有函数也是平等的,只不过只有main函数可以作为工程的入口函数而已。

链接(汇总成一个目标文件)

由汇编程序生成的目标文件并不能立即就被执行,其中可能还有许多没有解决的问题。例如,某个源文件中的函数可能引用了另一个源文件中定义的某个符号(如变量或者函数调用等);在程序中可能调用了某个库文件中的函数,等等。所有的这些问题,都需要经链接程序的处理方能得以解决。
  由此,我们可以理解了经常报错的一些情况,就是未解决符号表和导出符号表之间没有定义或者重复定义的情况的。
 

外部文件夹的h和cpp文件

外部文件夹的cpp文件并不能生成单独的编译文件,所以,不参与未解决符号表和导出符号表的生成,而#include外部的h头文件也只是复制进来头文件中的函数声明而已,没有定义。所以当需要使用外部文件夹的cpp文件的时候,直接在头部加上#include cpp文件,或者在头部#include h文件,尾部#include cpp文件,就相当于我们平时写的自定义函数一样。
 文章来源地址https://www.toymoban.com/news/detail-447227.html

到了这里,关于C++ 中到底是应该include .h文件还是应该include .cpp文件的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【C++】源文件.cpp和头文件.h分离编程

    将C++代码分为头文件(.h)和源文件(.cpp)的做法有以下几个好处: 模块化和代码组织:将函数和类的声明(包括函数原型、类的成员和属性等)放在头文件中,将函数和类的实现(具体的函数逻辑、成员函数的定义等)放在源文件中。这种分离有助于对代码进行模块化和组

    2024年02月09日
    浏览(28)
  • dhcp应该开启还是关闭(dhcp应该开启还是关闭)

    最好是开启。dhcp服务关闭后,上网设备需要手动设置ip地址才能上网。 1、开启DHCP功能时,只要客户端的状态是自动获取IP地址,服务器端就对客户端动态的分配P地址。如果客户端是手动配置好的IP地址,那么客户端不会再去服务器端申请P地址了。 2、关闭DHCP功能时,自动获

    2024年02月04日
    浏览(72)
  • 一个企业级的文件上传组件应该是什么样的

    目录 1.最简单的文件上传 2.拖拽+粘贴+样式优化 3.断点续传+秒传+进度条 文件切片 计算hash 断点续传+秒传(前端) 断点续传+秒传(后端) 进度条 4.抽样hash和webWorker 抽样hash(md5) webWorker 时间切片 5.文件类型判断 通过文件头判断文件类型 6.异步并发数控制(重要) 7.并发错误重试 8.慢

    2024年02月15日
    浏览(32)
  • C++ 判断路径为文件夹还是文件

    头文件 Path   指定标识文件的路径名。根据所使用的接口,此名称的解释不同。如果指定了DirFileDescriptor并且Path是一个相对路径名,那么Path被认为是相对于DirFileDescriptor指定的目录的。 Buffer 指定指向在其中返回信息的状态结构的指针。stat结构在sys/stat.h文件中描述。 成功完

    2024年02月01日
    浏览(101)
  • 如何用C++判断一个系统是16位、32位还是64位?

    如何用C++判断一个系统是16位、32位还是64位? 方法一:使用指针的sizeof()判断 方法二:使用整数溢出来判断 不同系统的基本数据类型的字节长度区别,如下表: 平台/类型 char short int long long long 16位 1 2 2 4 8 32位 1 2 4 4 8 64位 1 2 4 8 8 方法三:使用预定义宏来判断

    2024年04月13日
    浏览(29)
  • 到底叫 集合还是数组还是list还是列表?

    1 总体上可以将数据结构分为数组和集合两种,而列表是一个泛指 2 数组 -- 有序的,但长度是固定的-元素数量固定并且需要频繁访问,那么使用数组可能更合适 3 集合 3.1 list  -- 支持添加和删除元素,或者元素的数量不确定,就可以使用List类型 3.2 set -- Set是一种不允许重

    2024年02月14日
    浏览(26)
  • 【一文清晰】单元测试到底是什么?应该怎么做?

    我是java程序员出身,后来因为工作原因转到到了测试开发岗位。测试开发工作很多年后,现在是一名自由职业者 1、什么是单元测试 2、该怎么做单元测试 单元测试(unit testing),是指对软件中的最小可测试单元进行检查和验证。至于“单元”的大小或范围,并没有一个明确

    2024年02月07日
    浏览(35)
  • 登录应该是POST还是GET?

    在开发web应用程序时,登录模块是经常使用到的一个模块。然而,对于一个登录请求,我们应该使用哪种HTTP方法呢?是使用POST还是GET呢?本篇文章将会给出答案。 POST和GET: 在web开发中,HTTP协议有两种常见的请求方法:GET和POST。两种请求方法的主要区别有以下三点。 1. 参

    2024年02月06日
    浏览(25)
  • 应该选择网络安全还是程序员?

    很长的时间我都在思考这个问题.,根据自己的经验和朋友们的讨论后得出了一些结论,网络安全 这个概念太广,我就以安服/渗透岗作为比较的对象,题主可以参考一下: 程序员: 优点: 1.薪资非常高,今年校招大厂普遍是24K*15 2.岗位多,无论大城市还是小城市遍地是岗位

    2023年04月19日
    浏览(56)
  • Vue3 中应该使用 Ref 还是 Reactive?

    你可能会好奇:为什么我们需要使用带有  .value  的 ref,而不是普通的变量?为了解释这一点,我们需要简单地讨论一下 Vue 的响应式系统是如何工作的。 当你在模板中使用了一个 ref,然后改变了这个 ref 的值时,Vue 会自动检测到这个变化,并且相应地更新 DOM。这是通过一

    2024年02月20日
    浏览(33)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包