我应该把C++ #include放在哪里?在标头中还是在实现中?
Where should I put C++ #include's? In the header or in the implementation?
>假设我在文件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
到另一个类型的头文件中。 相反,应该创建第三个头文件来聚合这些类型。
- Linux 源代码中普通磁盘文件的"轮询"功能在哪里实现?
- 我有一个启用了代理存根支持的 ATL 项目,在哪里可以找到 xdlldata.h 文件中所有方法的实现
- 他们实现的开源C编译器(gcc,clang)的实际标准在哪里
- 在哪里可以找到C 中新运营商的确切实现
- 在哪里以及如何定义成员变量?在头文件还是实现文件中?
- 在哪里查找 GCC 实现定义行为的实现?
- 在哪里实现哈希函数
- 堆栈在哪里实现
- 在哪里可以找到sprintf的现有实现
- 我应该在哪里实现我的类方法
- 在哪里/如何声明和实现必须由成员方法使用的帮助函数
- 我如何实现bubblesort以及在哪里实现
- c++ Windows窗体应用程序——在哪里实现OnInitDialog()
- 在哪里实现堆栈类(在非递归二进制搜索函数中使用)
- 在哪里可以找到散列/加密算法的开源实现(头文件)
- C/ c++中定义的操作符在哪里,它们在这些语言中是如何实现的
- 阻塞队列实现:争用条件在哪里?
- 我应该在哪里重新实现QAbstractItemModel::supportedDragActions()
- 在哪里编写类的实现
- 在哪里可以找到++操作符的实现