编码C++(大部分)在头文件与.cpp文件中
Coding C++ (mostly) in header files vs .cpp files
多年来,我一直以标准方式编写C++代码,在头文件.hpp中使用类声明,在源.cpp文件中使用函数定义。 最近,我搬到了一家新公司,那里的代码(似乎受到boost编码风格的影响)完全用.hpp文件编码,有一个短.cpp文件来包含头文件并创建对象/程序二进制文件。
这让我思考 - 与为每个对象编写.hpp和.cpp文件相比,在头文件中编写代码的优点/缺点是什么?这假设我们的项目没有创建公共库,然后链接到程序二进制文件,而是每个程序二进制文件都是从头文件(和一个源文件)的总和构建的.cpp。这是C++的新趋势吗?
例如,模板对象只需要是头文件,但将非模板类放入头文件中,然后简单地将这些常见的项目类包含在二进制文件中似乎是个好主意。 假设您从头开始创建新的代码库,这是否意味着更少的链接,这可能意味着更少的链接错误和可能更快的构建。 预编译的头文件工具是否也意味着使用头文件可以加快构建时间? 还是构建时间更长,因为我们现在需要在创建二进制文件时编译所有代码,而不是链接公共共享库对象?
另请注意,我们在这里不是在编写 API(在这种情况下,像 pimpl 习语这样的东西会通过隐藏实现为我们提供更大的灵活性),我们正在编写在客户站点上运行的程序。
提前感谢,
在我的头顶上:
优势:
- 实现可见(更多的是弱点,但取决于情况)
- 无需导出到库
- 编译器优化某些代码的机会更大
弱点:
- 实现可见
- 构建时间较慢
- 臃肿的头文件 实现
- 中的更改需要完全重建,将实现放在实现文件中不会(仅编译该特定文件或库)
- 对于循环依赖项,请使用前向声明,并且仅在实现文件中包含完整类型。如果您只有一个标头,则不再可能。
我相信还有其他人,如果我能想到更多,我会编辑。
仅标头库往往会使构建系统更容易,通常您需要较少关心依赖项。
另一方面,将代码移动到实现文件可以更轻松地控制模块边界和创建可交换的二进制模块,这可以改进增量构建。成本更多的是"家政"。我的预感是更喜欢实现文件,并且有一些数据点支持我,例如来自提议的Boost网络库作者的这篇博客文章。
公共库是一回事,代码的一般可重用性是另一回事。如果要使用在另一个项目中编写的某些代码,则可能需要复制粘贴大量代码,然后维护单独的代码库。编译时间会变长,因为程序将是一个大的编译单元,而不是许多 cpp/h 文件,其中只有这些包含修改后的头文件的文件将被重新编译。例如,我目前正在处理的应用程序的完整构建需要 7 分钟。如果更改不严重,重新编译需要 ~ 15 秒。最后,代码的可读性可能较低。通过头文件,您可以快速浏览创建类的目的以及如何使用它。如果类是就地编写的,则必须不必要地挖掘源代码。
- .cpp和.h文件中的模板专用化声明
- 为什么两个不同的未命名名称空间可以共存于一个cpp文件中
- 命名空间中具有.h和.cpp文件的类
- 为什么我的主文件.cpp不打印头文件中的任何内容
- 生成文件错误 - 找不到文件 - *.cpp
- 如何在文件.cpp gtkmm中声明小部件
- 没有实现文件(.cpp)的派生类
- 如何使用"CMakeLists.txt"中的add_library将整个文件(.cpp,.h等)包含在目录中
- 如何在Linux / Windows操作系统上使用文件*.cpp一步编译下面的代码
- 关于 Linux .so 文件无法链接到主文件.cpp文件
- 文件.cpp从Windows到Linux
- Ubuntu C++ 编译器错误: g++: 错误: 文件.cpp: 没有这样的文件或目录
- 如何将文件.cpp编译为本机编译
- 使用模板类时,似乎无法包含除 main 以外的任何 cpp 文件.cpp
- 无法编译C++文件.cpp。C++98模式
- 为什么C++头文件不需要包含实现文件 (.cpp)
- 如何访问位于独立文件(.cpp)中的非成员函数
- 如何在Visual Studio Code中通过键盘快捷键切换头文件/cpp文件
- 如何将数据从stringstream写入文件(CPP)
- 为什么filestream不把空白写入文件cpp ?