我应该把C++ #include放在哪里?在标头中还是在实现中?

Where should I put C++ #include's? In the header or in the implementation?

本文关键字:实现 在哪里 我应该 C++ #include      更新时间:2023-10-16

>假设我在文件CameraVision.cpp中有一个名为CameraVision的类。

此类的构造函数接受 IplImage* 向量(IplImage 是一个 C 结构,表示 OpenCV 中的图像(。我需要在CameraVision.hpp或CameraVision.cpp中 #include opencv.h。

哪个更好,为什么?(#including 这些在CameraVision.hpp或CameraVision.cpp?(

另外,我应该在哪里#include STL <vector><iostream>等?

假设 CameraVision .cpp 的客户端也使用 <vector><iostream> 。客户显然会#include CameraVision.hpp(因为他是CameraVision的客户(。如果CameraVision的客户.cpp是否也应该 #include,<iostream>等,如果他们已经在CameraVision.hpp #include?客户怎么会知道这一点?

这里的规则是:限制范围。如果您可以仅将包含包含在实现文件中(例如,通过使用前向声明,包括<iosfwd>等(,那么这样做。在公共接口中,即客户端将包含的标头以使用您创建的库,请考虑使用 PIMPL 模式来隐藏任何实现细节。

好处:

1(代码的清晰度。基本上,当有人在看头文件时,他正在寻找你的类是关于什么的。包含的每个标头都会向标头添加"范围":要考虑的其他标头,更多标识符,更多构造。在非常糟糕的代码中,每个标头都包含更多的标头,如果不了解整个库,就无法真正理解一个类。尝试将此类依赖项保持在最低限度可以更轻松地单独理解类的接口。("不要打扰IplImage内部的实际含义,或者它可以做什么 - 在这一点上,我们所需要的只是一个指向它的指针"(。

2(编译时间。由于编译器必须执行与 1( 中所述相同的查找类型,因此头文件中包含的内容越多,编译源代码所需的时间就越长。在极端情况下,编译器必须包含每个翻译单元的所有头文件。虽然生成的编译时间对于一次性编译可能是可以接受的,但这也意味着在对标头进行任何更改后必须重新执行此操作。在紧凑的编辑 - 编译 - 测试-编辑周期中,这可能会很快加起来达到不可接受的水平。

编辑:不完全是主题,但是当我们在讨论它时,请不要在头文件中使用using,因为它与限制范围相反......

为了避免额外的包含,应在所有情况下在实现 (.cpp( 文件中使用 #include,除非在模块导出的原型或声明中使用要导入的名称。

例如:

傅炯:

#ifndef _FOOBAR_H_
#define _FOOBAR_H_
#include <vector>
void foo();
std::vector<int> bar();
#endif // _FOOBAR_H_

foo.cpp:

#include "foo.h"
#include <iostream>
void foo() {
    std::cout << "Foo";
}
std::vector<int> bar() {
    int b[3] = {1, 2, 3};
    return std::vector<int>(b, b+3);
}

如果仅在实现文件中使用/引用类型,而不是在头文件中使用/引用类型,则应仅在实现文件中#include,坚持有限范围的原则。

但是,如果头文件

引用某个类型,则头文件应#include该类型的头文件。 原因是您的头文件应该能够完全理解并在#included时拥有所需的一切。

这种观点的一个理由不仅是构建/编译,还有工具。 您的开发环境可能会解析头文件以为您提供类型帮助(例如智能感知、命令完成等(,这可能需要完整的类型信息才能正常工作。

另一个理由是,如果您的头文件被另一方使用,则该参与方有足够的关于您的类型的信息来使用您的代码。而且他们不必#include多个文件来编译一种类型。

不应仅仅为了避免在实现文件中#include两个文件,就不应将一个类型的头文件#include到另一个类型的头文件中。 相反,应该创建第三个头文件来聚合这些类型。