C文件需包含其头文件已包含内容吗?解析Google C++风格指南矛盾点
当然不需要!你写的.c文件只需要老老实实包含它自己对应的.h就够了——毕竟这个.h就是为了给.c服务而生的,它的本职工作之一就是把.c需要的各种公共依赖、类型声明、函数原型都整理好。举个实际例子:如果foo.h里已经写了#include "bar.h",那foo.c只要#include "foo.h",就能直接用bar.h里的所有符号,完全没必要再重复写一遍#include "bar.h"。
不过这里有个小提醒:要是哪天维护foo.h的人把里面的#include "bar.h"删掉了,你的foo.c可能会突然编译失败。但按照规范来说,foo.h的变更应该保持向后兼容——如果它之前默认给foo.c提供了bar.h的符号,那移除前要么提前说明,要么通过其他方式(比如自己声明必要的符号)来避免炸锅。
这俩规则一点都不矛盾,只是你没分清它们适用的不同场景而已!我给你拆解开讲:
首先看第一条规则:
如果您依赖bar.h中的符号,不要依赖于您已包含的foo.h(当前)包含bar.h这一情况,请自行包含bar.h,除非foo.h明确表明其意图是为您提供bar.h的符号。
这条管的是跨模块的依赖场景。比如你现在写的是baz.cc,它里面包含了foo.h,而foo.h碰巧自己包含了bar.h。这时候baz.cc要是想用bar.h里的东西,绝对不能图省事依赖foo.h的间接包含,必须自己主动#include "bar.h"——因为foo.h的存在是为foo.cc服务的,它包含bar.h只是自己的需求,不是为了给baz.cc送福利。哪天维护foo.h的人觉得不需要bar.h了,把那行include删掉,你的baz.cc直接就编译报错,找都找不到原因。
再看第二条规则:
但相关头文件中已有的#include,无需在对应的cc文件中再次包含(即foo.cc可以依赖foo.h中的#include)。
这条管的是同模块内的源文件和头文件场景,也就是foo.cc和它亲爹foo.h——这俩是绑定死的,foo.h从设计之初就是为了给foo.cc提供必要的支持。所以foo.cc完全可以放心依赖foo.h里的所有include,不用再重复写一遍那些头文件。
说白了就是两个核心原则:
- 跨模块:别蹭别人的间接依赖,自己要的东西自己拿,避免被别人的修改坑。
- 同模块:放心用自己头文件里的所有内容,毕竟那就是为你准备的,省得重复写代码。
这样一看,两个规则不仅不矛盾,反而配合得很好,都是为了让代码更健壮、更好维护。
内容的提问来源于stack exchange,提问作者kvu787

