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

news2024/11/24 18:28:43

在阅读一个较大的解决方案中,对于其他文件夹下的.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的名字是否合法。
语法分析 – 识别短语和句型的语法属性;
语义分析 – 确认单词、短语和句型的语义特征;
代码优化 – 修辞、文本编辑;
代码生成 – 生成译文。
内联函数的替换就发生在这一阶段。

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

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

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

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

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

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

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

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

外部文件夹的h和cpp文件

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/518685.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

连接器:一种可靠耐用、节约成本的同为科技(TOWE)工业连接器

随着我国经济建设水平的飞速发展,工业连接器被广泛应用于工业、化工、机场、船舶、码头、建筑、铁路、医疗、会展、商业演出等领域。工业连接器的作用是用于连接一个电路导体与另一个电路导体、或一个传输元件与另一个传输元件的装置,并且为两个电路子系…

知识变现海哥:六种常见的知识变现渠道

什么是知识变现?就是用你所会的知识技能,在网上进行展示,吸引人们为其付钱。互联网发展到今天,我们可以看到它各方面已经逐渐完善了,但曾经在互联网上的不花钱的知识,在今天却要为其花费金钱。在此基础上&a…

CCSA TC1演讲分享 | 全域智能,构建平台化生态

日前,中国通信标准化协会(CCSA)成功召开互联网与应用技术工作委员会(TC1)第四十次全会,全会期间,TC1 WG7 IT内控与审计技术标准工作组举办了第3次工作组会议。此次会议重点讨论了各项标准文稿及…

微服架构基础设施环境平台搭建 -(四)在Kubernetes集群基础上搭建Kubesphere平台

微服架构基础设施环境平台搭建 -(四)在Kubernetes集群基础上搭建Kubesphere平台 通过采用微服相关架构构建一套以KubernetesDocker为自动化运维基础平台,以微服务为服务中心,在此基础之上构建业务中台,并通过Jekins自动…

Docker安装及容器安装

Docker安装及容器安装 一、Docker简单介绍 1、Docker是什么 Docker是基于Go语言实现的云开源项目。 Docker是一个开源的应用容器引擎,是容器技术的一种,采用Go编程语言编写。虽然 Docker把容器技术推向了巅峰,但其实,还有其他容…

蓝牙智能升降桌解决方案介绍

传统桌子在办公和学习中具有很大的普及度,但是长时间久坐却会对人体造成可怕的危害。由于不合理的坐姿、长时间久坐等习惯,不仅影响血液循环,让人体感到不适,还会出现视力、颈椎、腰椎、心脏等一系列健康问题。此外,传统桌子通常是固定高度且…

【C++进阶2--多态】面向对象三大特性之一,多种形态像魔法?

今天,带来C多态的讲解。 多态和继承并用,能产生“魔法般的效果”。 *文中不足错漏之处望请斧正! 见见多态 是什么 使得父类指针或引用有多种形态。 怎么使它有多种形态呢?咱们先见见猪跑。 见见猪跑 class Base { public:v…

第05章_排序与分页

第05章_排序与分页 1. 排序数据 1.1 排序规则 使用 ORDER BY 子句排序 ASC(ascend): 升序DESC(descend):降序 ORDER BY 子句在SELECT语句的结尾。 1.2 单列排序 SELECT last_name, job_id, department_id, hire_date FROM …

Java基础学习(15)

Java基础学习 一、IO流进阶1.1 缓冲流1.1.1字节缓冲流1.1.2 字符缓冲流 1.2 转换流1.3 序列流1.4 反序列化流 /对象操作输入流1.4.1 序列化流/反序列化流的细节汇总 1.5 打印流1.5.1 字节打印流1.5.2 字符打印流 1.6 解压流、压缩流1.7 Commons-io1.8 hutool工具包 一、IO流进阶…

【C#】RemoveAt索引越界问题

系列文章 【C#】单号生成器(编号规则、固定字符、流水号、产生业务单号) 本文链接:https://blog.csdn.net/youcheng_ge/article/details/129129787 【C#】日期范围生成器(开始日期、结束日期) 本文链接:h…

使用FFMPEG和SDL2实现音视频同步的简易视频播放器

程序框架 由于之前都是针对FFMPEG某一个功能做的测试和学习。这里我简单做了一个视频播放器,并简单做了音视频同步。在此记录大致过程。 大致框架如下: 主线程 1.加载视频文件,查找音视频流信息 2.初始化音视频解码器 3.初始化SDL并设置…

题解校验码—CRC循环校验码与海明校验码

码距 一个编码系统的码距是任意两个码字的最小距离。 例如个编码系统采用三位长度的二进制编码,若该系统有四种编码分别为:000,011,100,111,此编码系统中000与111的码距为3;011与000的码距为2…

POE:性价比最高的 AI 整合网站

创作不易,如果本文对你有帮助,胖友记得一键三连 😭。更多 AI 优质内容推荐请关注主页 “AI” 专栏,笔者会不定期更新觉得自己用下来还不错的 AI 相关产品。 1.介绍 Poe 是一款同时整合了 ChatGPT、Sage、GPT-4、Claude、Claude-in…

经典神经网络(2)AlexNet及其在Fashion-MNIST数据集上的应用

2、深度卷积神经网络AlexNet ImageNet 数据集:一个开源的图片数据集,包含超过 1400万张图片和图片对应的标签,包含2万多个类别。 自从2010 年以来,ImageNet 每年举办一次比赛,即:ImageNet 大规模视觉识别挑…

数组排序算法

数组排序算法 一、冒泡排序算法二、直接选择排序三、插入排序四、反转排序 一、冒泡排序算法 冒泡排序算法: 类似气泡上涌的动作,会将数据在数组中从小到大或者从大到小不断向前移动。 基本思想: 冒泡排序的基本思想是对比相邻的两个元素值&…

并发编程(二) — 内存可见性问题

目录 前言 内存可见性问题 synchronized volatile CAS算法 CAS算法原理 CAS算法应用场景 CAS算法代码实现 参考目录 前言 在谈共享变量的内存可见性问题之前,先谈谈线程安全问题 ,线程安全问题是指当多个线程同时读写一个共享资源并且没有任何同…

c高级day4作业

有m1.txt m2.txt m3.txt m4.txt,分别创建出对应的目录,m1 m2 m3 m4 并把文件移动到对应的目录下使用break关键字打印九九乘法表,提示:printf "%d * %d %d" $i $j $((i*j)) #!/bin/bash for i in m1 m2 m3 m4 do#文件夹…

只限今日免费,Midjourney 5.1震撼更新!逼真到给跪,中国情侣细节惊艳,3D视频大片马上来

来源 | 新智元 微信号:AI-era 【导读】全新升级的Midjourney让全网又疯狂了,创造力解禁,出图更逼真。重要的是,限时免费到今天,要玩的抓紧了。 一个月前,Midjourney V5画的一对中国完美情侣在网上爆火&am…

涅槃重生,BitKeep如何闯出千万用户新起点

在全球,BitKeep钱包现在已经有超过千万用户在使用。 当我得知这个数据的时候,有些惊讶,也有点意料之中。关注BitKeep这几年,真心看得出这家公司的发展之迅速。还记得2018年他们推出第一个版本时,小而美,简洁…

python和pycharm的安装(安装包免费下载共享)

说明: 本文内容包括Python和Pycharm安装。 一、python安装: python是一门编程语言,安装python是为了能在电脑上使用这门语言。 1、python下载 下载链接:https://pan.baidu.com/s/1mWsJjO8HngNQtINCzu0bBA 提取码:9…