现在快2022年了,c++为什么还要实现(.cpp)和声明(.h)分开?

2023-05-16

像 Java 或 C# 都不需要声明头文件,C++ 委员会为什么不解决这个问题?

都有人贴stackoverflow的解答了,居然没人翻译,我来翻译一下,顺便夹点私货。

Why does C++ need a separate header file?stackoverflow.com/questions/1305947/why-does-c-need-a-separate-header-fileimg

<翻译>

有些人认为的头文件的好处

  • 头文件机制允许/强迫程序员分离实现和声明,单总体来说事实并非如此。头文件有大量的实现细节,比如非public接口的成员变量,比如函数直接在类定义中实现。实操层面这种分离完全没有实现。
  • 头文件加速编译,因为每个单元可以独立编译。实际上C++是编译速度最慢的语言,而其中的一个原因就是叠床架屋的重复的头文件包含。反复的交叉的包含导致编译不同单元的时候头文件被反复解析。

实际上,头文件是来自70年代产生的C语言。那个年代的计算机内存小,不太可能把整个模块全部放在内存里。编译器处理文件就是从头读到尾,有了头文件编译器就可以这么做。(按,编译器可以把头文件当作文本替换直接拿进来用,但是又不用编译实现。)

C++为了向后兼容就用了这套系统。

放在今天,这个做法没有意义,既没有效率,又容易出错,还过分复杂。如果语言设计的目标是分离接口定义和实现,有的是别的办法。

C++0x本来就考虑过模块系统,想法和Java/C#类似,但是优先级不够就没做。(按,C++20的确有module系统了)。

</翻译>

以下私货

有人说可以分离定义和接口,我觉得头文件的确在某种程度上可以做的这点,实操中虽然不完美也就能用。有人说头文件可以用来在不分享源代码的情况下分享接口,也对。有人说这是为了和C的反向兼容,这的确是原因。

就题主的问题而言,为什么2022年了还要分开。答案很简单,因为是C++,C++就是祖宗之法不可变,祖传的C/C++怎么能说废就废,肯定得反向兼容。

就头文件的目的而言,上面说的接口和实现分离的确是可以用头文件来实现的。但要注意的是,对于没有包袱的语言来说,头文件并非实现这点的最佳解决方案。事实上包这种概念就比头文件好得多。

从实现上来说,Java/C#的二进制模块可以自带符号表和注释,那二进制模块本身就自带头文件信息了(实际上是从源代码编译出来抽象接口)。我既然可以用这样的包和类文件里抽象出一个定义,在IDE的支持下,它不比一个头文件香吗。我根本不用担心重复包含,循环引用之类的问题。和客户分享,我既可以分享自带定义信息的二进制模块,也可以选择只分享定义接口(但是最后客户总会需要你的二进制模块)。希望C++的模块也能早日普及。

说C++历来如此的,历来如此不表示这是对的。

说不喜欢头文件别用C++的,C++一大坨东西,有好有坏,头文件并非其中的精华。不好的改进了才好。


已经不用了。

C++20 有了模块,并且有一种名为“私有模块片段”(private module fragment, [module.private.frag])的机制,它适用于一体化的写法。

私有模块片段这种机制使得一个翻译单元(同时它也是模块单元,并且需要是该模块中唯一的模块单元)中同时有导出和非导出的部分(正常来说分别用于接口和实现),从而就不需要接口和实现分成不同文件了。

示例:

export module my.unified.unit;
// 此处为接口部分
export int fun();

module : private;
// 此处为实现部分
int fun() { return 42; }

其它答主答的已经很好了,这里从另一些角度,让C/C++新手理解为什么这不是一个问题,反而是一个feature。

1、C/C++源码不只有.c、.cpp、.cc、.h,还可以是.inc、.abc、.txt等等任意后缀

什么?.inc是啥?

当然,你在任何一本C/C++教材中都不会看到这种用法。理解它的关键是要理解“预编译器”的运作原理,理解#define和#include的真正含义。

预编译器,本质上是一种单纯的文本替换工具。所以无论你#include什么东西,预编译器都会原样照搬,甚至你#include一张图片也不是不可能(?)。

预编译器只是忠实完成它的本职工作,一方面,你需要理解预编译的常规用法,比如避免头文件包含多次:

#ifndef __A_H__
#include "a.h"
#endif

另一方面,在深入使用C/C++时,你要意识到以上写法并非什么“本质标准”,并不是谁规定一定要这么写,它只是一种常用写法,而非本质。只要你对预编译理解够深入,还能玩出各种花样来。

使用.inc、.txt等后缀,是为了既要让#include包含inc文件的内容,又不让IDE自动处理它,是一种较常见的变通方案。

2、链接

现代人学习C/C++,大都是用IDE,新建工程,写好h,写好cpp,然后build all,搞定。

这个过程跳过了十分重要的一步——链接。

每个c或cpp文件,会被编译为一个“编译单元”,一般是.o文件。之后,还要把这一堆.o文件,加上库文件,链接成完整的、最终的执行文件。

在C/C++原始标准中,其实对链接的定义是十分开放的,不同的编译器、不同的操作系统应该如何链接各有不同的实现。这种灵活的标准带来两个结果:

  1. 高手可以自定义链接过程,精确定义执行文件的结构,以满足破解、加密、加壳等各种高级需求。
  2. 普通用户只会自动编译,对链接过程细节一窍不通。

链接的过程还是比较深奥的,这里不打算在一个短短的回答中讲清楚。有兴趣可以看一本书:《程序员的自我修养——链接、装载与库》

img

3、声明与定义

你可以不理解链接过程,但是有一个相关知识点有必要搞清楚——声明与定义。

extern int a;    // 外部变量声明
int g = 0;       // 全局变量定义,由于有初始化,定义较强
int g2;          // 全局变量定义,没有初始化

int func(int a); // 函数声明
int func(int aa)
{
    return 0;
}  // 这是函数定义

static int s_func(int a) { ……}    // 这叫静态函数定义(被限定于模块内,有点模块私有那意思)

声明和定义最大的区别是:声明可以重复多次,而定义只能有一个。这对我们设计.h文件提出了限制——头文件里最好只有声明,没有定义。

声明与定义的区别是C/C++很重要的一个特点。但是很多人对它一知半解,造成了重复定义、模块划分不合理、嵌套定义、链接时间过长等等问题。

总而言之

C/C++把问题搞得这么复杂,不是多此一举,反而是十分有必要的。

当然未来C++的改进中,会加入更现代化的包管理方式,改进原始的链接方式。但是C语言应该不会接受这么剧烈的变化。

当你了解足够多的时候,你会发现C/C++提供了非常底层的控制方法,没有做不到,只有想不到。当然这给我们日常开发带来一些复杂度,但另一方面,也给技术进步留下了尽可能大的探索空间。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

现在快2022年了,c++为什么还要实现(.cpp)和声明(.h)分开? 的相关文章

  • 基于模型的系统工程(MBSE)与设计(MBD)的关系思考

    已剪辑自 http www clii com cn lhrh hyxx 201905 t20190522 3934609 html 导读 xff1a 如何将关于功能知识表达的建议与任何系统工程建模语言的任何部分结合起来 xff0c 确定地
  • 从MBD到MBE的战略转型路径

    已剪辑自 https zhuanlan zhihu com p 58927567 导读 xff1a 企业的不断成功 xff0c 源于在每个关键机遇期做出正确的抉择 对于在国民经济中发挥重要作用的中国制造业企业来说 xff0c 如何面向未来
  • SysML教程

    已剪辑自 https www jianshu com p 6ba96913abcc SysML是一种支持复杂系统分析 规范 设计 验证和确认的通用图形化建模语言 这些系统可能包括硬件设备 软件数据 人员 规程 设施 xff0c 以及其他人造
  • 程序运行原理:程序是如何运行又是如何崩溃的?

    已剪辑自 https time geekbang org column article 166581 软件的核心载体是程序代码 xff0c 软件开发的主要工作产出也是代码 xff0c 但是代码被存储在磁盘上本身没有任何价值 xff0c 软件
  • 分布式系统

    简介 在一个分布式系统中 xff0c 一组独立的计算机展现给用户的是一个统一的整体 xff0c 就好像是一个系统似的 系统拥有多种通用的物理和逻辑资源 xff0c 可以动态的分配任务 xff0c 分散的物理和逻辑资源通过计算机网络实现信息交
  • #如何写好技术文档——来自Google十多年的文档经验

    文章目录 文档的重要性为什么大多数人都不喜欢写文档 xff1f 如何产出高质量文档像管理代码一样管理文档明确你的读者是谁清晰的分类参考文档设计文档引导类文档概念性文档Landing pages 落地页 文档Review 写文档的哲学5W法则
  • 如何写好技术文档?

    文章目录 01为什么需要写文档 xff1f 02写文档的重要性03像管理代码一样管理文档04文档类型05文档Review06文档写作的哲学07结论 已剪辑自 https cloud tencent com developer article
  • 数据库系统原理1

    第一章 数据库管理技术发展的不同阶段形成不同的特点 数据描述经历了三个阶段对应于三个数据模型 第二章 数据库系统的生命周期 xff0c 书中可能和我们学习软工的时候有些出入 xff0c 其实就是不同时间有不同的理解 xff0c 横看成岭侧成
  • ssh 登录时常出现的几种错误以及解决方法(Linux)

    ssh 登录时常出现的几种错误以及解决方法 xff08 Linux xff09 参考网址 xff1a https blog csdn net GX 1 11 real article details 80423409 前言 ssh是Linu
  • 程序员既要写好代码,又要写好文档

    转载于 xff1a https developer aliyun com article 196898 作为一个长期混迹于CSDN社区的人 xff0c 我对很多拥有高访问量的博主钦佩不已 xff0c 特别是在参加了CSDN在举办 2014
  • 一步一步教你如何写开发文档

    已剪辑自 https icocos github io 2017 01 02 E4 B8 80 E6 AD A5 E4 B8 80 E6 AD A5 E6 95 99 E4 BD A0 E5 A6 82 E4 BD 95 E5 86 99
  • 如何写好项目文档

    已剪辑自 https blog csdn net houzhizhen article details 105622282 引子 有太多的程序员 xff08 包括很多资深的程序员 xff09 不会写文档有太多的项目没有 xff08 完整的
  • 怎样才能写好项目文档?

    已剪辑自 http learn lianglianglee com E4 B8 93 E6 A0 8F E8 BD AF E4 BB B6 E5 B7 A5 E7 A8 8B E4 B9 8B E7 BE 8E 16 20 E6 80 8E
  • 技术文档写作基础-写作新手必看

    文章目录 1 搞清楚主谓宾2 不滥用代词 过渡词和标点符号2 1 不滥用代词和过渡词2 2 不滥用标点符号 3 多用强势动词 xff0c 少用形容词和副词3 1 强势动词和主动语句3 2 少用形容词和副词 4 正确使用术语5 正确使用段落5
  • 软件工程及其文档汇总

    文章目录 软件文档作用和分类作用分类 管理和维护软件工程的文档有哪些 xff1f 软件工程各类开发文档的作用软件工程各文档模板系统定义文档需求规格说明书概要设计说明书用例文档详细设计说明书测试计划测试分析报告 xff1a 软件文档 软件文档
  • 中断和异常,C/C++语言异常,实时操作系统对中断和异常的处理

    文章目录 一 中断和异常是什么1 中断和异常的定义2 中断处理的过程3 常见中断和异常 二 C C 43 43 软件异常的常见原因分析与总结1 概述2 引发软件异常的常见原因2 1 变量未初始化2 2 死循环2 3 内存越界2 4 内存泄漏
  • 编程中什么情况下需要加 volatile?

    文章目录 一 CPU访问变量 1 给变量赋值 2 读变量的值 二 编译器优化 1 上面程序执行过程有什么缺点 xff1f 2 为什么要优化 xff1f 三 volatile到底有什么用 xff1f 用在什么场合 xff1f 1 在执行b 6
  • ImageJ实用教程汇总

    https zhuanlan zhihu com p 60999196
  • 第一性原理详解

    文章目录 百度百科其他解释补充解释 智库百科什么是第一性原理如何运用第一性原理第一性原理思考举例 什么是第一性原理 xff0c 它有什么重要意义 xff1f 详解马斯克的 第一性原理 01什么是 第一性原理 思维 xff1f 其实是一种演绎
  • Win8.1电脑声音可以外放但是插入耳机没有声音

    今天早上正准备学习英语 xff0c 发现耳机插入电脑没有声音 xff0c 于是开始找百度 xff0c 一步一步剥茧抽丝去查找问题来源 问题 xff1a 点击喇叭出现如下图片 xff1a 平常只有右半个图现在却有两个图标了 步骤 xff1a

随机推荐

  • 如何写好技术文档——来自Google十多年的文档经验

    已剪辑自 https zhuanlan zhihu com p 393553478 本文大部分内容翻译总结自 Software Engineering at Google 第10章节 Documentation 另外 xff0c 该书电子版
  • 如何编写好的软件设计文档

    文章目录 为什么要写设计文档 设计文档中应该包含哪些内容 标题和人员 概述背景 目标和非目标 里程碑 现状 建议方案 替代方案 可测试性 监控和报警 跨团队的影响力开放性问题详细的范围和时间表如何编写尽可能简单尽可能使用图和图表包含数字试着
  • 软件开发总结

    文章目录 结构化方法Jackson方法原型方法面向对象方法敏捷方法水晶法并列争求法自适应软件开发 xff08 ASD 软件设计的演变过程序言结构化程序设计面向对象程序设计设计模式设计原则领域驱动设计DCI架构模式领域专用语言微服务架构模式小
  • 软件开发中会使用到的图

    文章目录 软件开发中会用到的图一 背景二 图为了解决什么问题三 不同流程中适合运用的图四 实际的运用五 结语 软件工程中的各种图软件工程用的15种图数据关系流图怎么画 xff1f 这款软件教你轻松绘制关系流图数据关系流图的常见用途数据关系流
  • 软件耦合的分类及解决方法

    文章目录 什么是耦合 解耦高内聚与低耦合耦合内容耦合公共耦合外部耦合控制耦合标 xff08 印 xff09 记耦合数据耦合非直接耦合 内聚 什么是解耦公共耦合 c语言例子 小小的公共库 xff0c 大大的耦合 xff0c 你痛过吗 xff1
  • 机器学习在分子模拟中的应用

    文章目录 一 背景二 分子动力学模拟介绍简史基本步骤应用发展方向 三 AlphaFold 前言 Alphafold2做了什么改进 Alphafold2会议具体细节 xff1a Alphafold为什么强 xff1f 学术问题 xff1a 四
  • 一个重要的问题:怎么寻找自己的终身事业呢?

    已剪辑自 https mp weixin qq com s OJX2FZ TtdPxWg1V6gr6gA 前文写过我们每一个职场人都应该寻找自己的终身事业 xff0c 而不是机械地打工赚钱维持生活生存的薪资 一些读者看完后跑过来问 xff1
  • 腾讯技术总监的转行感悟

    已剪辑自 https mp weixin qq com s 3bJVRGf91bThnZo74g3Sw 今天分享一个新东方在线前同事写的文章 xff0c 说来也巧他的文章写的人恰好是我下属老杨 老杨也代表了技术人到中年的一种转型思路 xff
  • 30多岁的每一步都很重要

    人生有不同阶段 xff0c 每个阶段都挺重要 xff0c 但最重要的是30岁 40岁这个阶段 30岁之前我们很难找到终身奋斗目标 很难构建多元化财务收入 很难成为行业专家 我们甚至还是懵懵懂懂的状态 xff0c 沉迷于某个并不重要的人 并不
  • 重要的是改变命运,而非升职加薪

    已剪辑自 https mp weixin qq com s biz 61 MzA3MzA5MTU4NA 61 61 amp mid 61 2247505468 amp idx 61 1 amp sn 61 1373f053179462101
  • SQL Server 2012 导出数据及分离MDF、LDF

    最近在设计数据库时看到自己设计的数据库和师哥师姐给我们的不一样 xff0c 于是就查了一下把数据库导出写了下来 分离数据库步骤 这是师哥师姐给我们的数据库格式 xff0c 如下 xff1a 那么如何生成MDF和LDF格式的数据库呢 xff1
  • 怎么找到贵人?

    已剪辑自 https mp weixin qq com s biz 61 MzA3MzA5MTU4NA 61 61 amp mid 61 2247506375 amp idx 61 1 amp sn 61 6008cc68a5967d3db
  • 14种主流的RTOS 单片机操作系统~来学!

    已剪辑自 https mp weixin qq com s YQGaBlluBWFbk01K5qCu A 单片机编程时 xff0c 我们都知道有两种基本操作 xff1a 裸奔和操作系统 所谓裸奔 xff0c 就是一个大循环往复执行 今天要讲
  • 读《工作多年后,嵌入式工程师的区别在哪儿?》有感

    读 工作多年后 xff0c 嵌入式工程师的区别在哪儿 xff1f 有感 已剪辑自 https mp weixin qq com s N32aKmTSmAAQ7KzLveKZRg 面试了很多人之后 xff0c 我开始思考 xff0c 一个工作
  • 嵌入式软件编程模式

    文章目录 嵌入式软件编程模式基于周期调用的运行模式基于中断的前后台运行模式基于事件队列的运行模式带时间信息的事件队列运行模式周期任务运行框架 整理自 xff1a AI嵌入式系统 xff1a 算法优化与实现 本章介绍嵌入式软件编程模式和通用软
  • 嵌入式AI入坑经历

    转载于知乎稚晖君 xff1a https zhuanlan zhihu com p 115598733 本文来自前几天 量子位 对我的采访内容 xff0c 文章里分享了一些我个人的心路历程和对开发者的建议 其实很多大家私信我的问题我以前都在
  • 嵌入式开发,从开发板到产品的过程是什么样的?

    始终搞不懂 xff0c 比如在51单片机 AVR或者树莓派等等的单片机开发板上开发出一套系统之后 xff0c 怎样进一步发展成为一个具体产品的 xff1f 这个过程是什么样子的 xff1f 举个例子说 xff1a 我在51单片机上完成了一个
  • 虚拟+现实:半实物仿真测试和全数字仿真测试有效保证嵌入式系统的健壮与可靠

    已剪辑自 http www kiyun com Show news cid 11 id 273 html 随着现代信息技术与软硬件技术的快速发展 xff0c 嵌入式系统的功能日益强大 xff0c 嵌入式设备和软件应用领域越来越宽泛 近年来
  • 全数字仿真测试工具Edst

    产品概述 全数字仿真测试工具是基于嵌入式处理器的全数字仿真 xff0c 在全数字仿真环境下 xff0c 对嵌入式C语言和汇编语言软件的分析 仿真运行 故障注入和软件测试等 全数字仿真测试工具适用于现代的嵌入式系统的验证 开发 测试和维护的全
  • 现在快2022年了,c++为什么还要实现(.cpp)和声明(.h)分开?

    像 Java 或 C 都不需要声明头文件 xff0c C 43 43 委员会为什么不解决这个问题 xff1f 都有人贴stackoverflow的解答了 xff0c 居然没人翻译 xff0c 我来翻译一下 xff0c 顺便夹点私货 Why