如果前者只提供后者定义的声明,那么我是否有理由在关联的cpp文件中包含一个标头



考虑具有以下内容的foo.cpp文件

#include "foo.hpp"
int foo() {
return 7;
}

及其相关联的报头

#pragma once
int foo();

后者显然需要意识到foo存在的以下main函数:

#include <iostream>
#include "foo.hpp" // to make the name `foo` available
int main() {
std::cout << foo() << std::endl;
}

然而,#include "foo.hpp"似乎是多余的。我有什么理由保留它吗?


我在我工作的代码库中看到过这种做法,但我想开源中有很多例子。例如,作为一个随机选取的示例,从fish-shell代码库中查看src/builtin_builtin.hsrc/builtin_bultin.cpp:前者在include保护之外,具有仅

  1. 一个CCD_ 8
  2. 两个类声明
  3. 以及函数声明

可以将2放在fwd头中,将其与1一起包含在cpp文件中,然后cpp文件就不需要再包含自己的头了。

C++以线性顺序处理文件。如果.cpp文件从同一.cpp文件调用其他方法,则定义需要继续调用,否则您需要.hpp中的声明。对于两个相互递归的函数,您确实需要至少一个声明。

此外,具有可用的类声明意味着编译器可以警告不匹配(由于重载,无法使用自由函数声明(

从其实现文件(fpp.cpp(中包含标头(fpp.hpp(的一些原因:

  1. 如果在foo.cpp中首先包含foo.hpp,那么foo.cpp的编译就相当于测试foo.hpp是自包含的,这意味着它可以在不首先包含任何其他内容的情况下成功编译。GoogleC++编码指南特别建议首先包含相关的头。

  2. foo.hpp最好声明foo.cpp导出的所有内容,而foo.cpp中的所有其他内容都具有内部链接,以免污染全局命名空间。GCC选项-Wmissing-declarations将报告与该实践的偏差,但仅当foo.cpp包括foo.hpp时才有效。

  3. 有时(事实上,经常(需要包含foo.hpp,因此foo.cpp将进行编译。最常见的情况是,foo.hpp定义了foo.cpp需要的类型,但也可能由于在定义之前使用而需要函数声明。我建议坚持这样做,而不是试图推断在每种情况下是否有必要。

  4. 有时,编译器可以诊断声明和定义之间的不匹配。我看到的一个讨厌的例子是,一个头声明了全局int x,但实现文件定义了long x。花一天的时间调试这个错误,我预测你会下定决心每次都包含相关的头!

最后,没有充分的理由不包含相关的标头。特别是,省略include几乎永远不会对编译时间产生可衡量的影响。方法可以通过重组标头依赖关系(例如,使用前向标头(来显著提高编译时间,但这不是其中之一。

鸣谢:BoP在评论中提到了第1点。MSchangers的答案注释第3点和第4点。

相关内容

  • 没有找到相关文章

最新更新