C++ .h 文件中应该包含哪些内容?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1945846/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What should go into an .h file?
提问by Enrico Tuvera Jr
When dividing your code up into multiple files just what exactly should go into an .h file and what should go into a .cpp file?
将您的代码分成多个文件时,究竟应该将哪些内容放入 .h 文件中,哪些内容应该放入 .cpp 文件中?
回答by Amber
Header files (.h
) are designed to provide the information that will be needed in multiple files. Things like class declarations, function prototypes, and enumerations typically go in header files. In a word, "definitions".
头文件 ( .h
) 旨在提供多个文件中所需的信息。类声明、函数原型和枚举之类的东西通常放在头文件中。一句话,“定义”。
Code files (.cpp
) are designed to provide the implementation information that only needs to be known in one file. In general, function bodies, and internal variables that should/will never be accessed by other modules, are what belong in .cpp
files. In a word, "implementations".
代码文件 ( .cpp
) 旨在提供只需要在一个文件中知道的实现信息。通常,其他模块应该/永远不会访问的函数体和内部变量属于.cpp
文件。一句话,“执行”。
The simplest question to ask yourself to determine what belongs where is "if I change this, will I have to change code in other files to make things compile again?" If the answer is "yes" it probably belongs in the header file; if the answer is "no" it probably belongs in the code file.
问自己确定什么属于哪里的最简单的问题是“如果我更改它,我是否必须更改其他文件中的代码才能再次编译?” 如果答案为“是”,则它可能属于头文件;如果答案为“否”,则它可能属于代码文件。
回答by paercebal
Fact is, in C++, this is somewhat more complicated that the C header/source organization.
事实上,在 C++ 中,这比 C 头文件/源代码组织要复杂一些。
What does the compiler see?
编译器看到了什么?
The compiler sees one big source (.cpp) file with its headers properly included. The source file is the compilation unit that will be compiled into an object file.
编译器看到一个大的源 (.cpp) 文件,其中包含正确的头文件。源文件是将被编译成目标文件的编译单元。
So, why are headers necessary?
那么,为什么需要标题?
Because one compilation unit could need information about an implementation in another compilation unit. So one can write for example the implementation of a function in one source, and write the declaration of this function in another source needing to use it.
因为一个编译单元可能需要有关另一个编译单元中实现的信息。因此,例如可以在一个源中编写函数的实现,并在需要使用它的另一个源中编写此函数的声明。
In this case, there are two copies of the same information. Which is evil...
在这种情况下,相同信息有两个副本。哪个邪恶...
The solution is to share some details. While the implementation should remain in the Source, the declaration of shared symbols, like functions, or definition of structures, classes, enums, etc., could need to be shared.
解决办法是分享一些细节。虽然实现应该保留在 Source 中,但共享符号的声明,如函数,或结构、类、枚举等的定义,可能需要共享。
Headers are used to put those shared details.
标题用于放置那些共享的详细信息。
Move to the header the declarations of what need to be shared between multiple sources
将需要在多个源之间共享的声明移至标题
Nothing more?
而已?
In C++, there are some other things that could be put in the header because, they need, too, be shared:
在 C++ 中,还有一些其他的东西可以放在头文件中,因为它们也需要共享:
- inline code
- templates
- constants (usually those you want to use inside switches...)
- 内联代码
- 模板
- 常量(通常是你想在开关中使用的那些......)
Move to the header EVERYTHING what need to be shared, including shared implementations
移动到标题所有需要共享的内容,包括共享的实现
Does it then mean that there could be sources inside the headers?
那么这是否意味着标题中可能有来源?
Yes. In fact, there are a lot of different things that could be inside a "header" (i.e. shared between sources).
是的。事实上,“头”中有很多不同的东西(即在源之间共享)。
- Forward declarations
- declarations/definition of functions/structs/classes/templates
- implementation of inline and templated code
- 前向声明
- 函数/结构/类/模板的声明/定义
- 内联和模板化代码的实现
It becomes complicated, and in some cases (circular dependencies between symbols), impossible to keep it in one header.
它变得很复杂,在某些情况下(符号之间的循环依赖),不可能将它保存在一个标题中。
Headers can be broken down into three parts
标题可以分为三个部分
This means that, in an extreme case, you could have:
这意味着,在极端情况下,您可以:
- a forward declaration header
- a declaration/definition header
- an implementation header
- an implementation source
- 前向声明标头
- 声明/定义标题
- 一个实现头
- 一个实现源
Let's imagine we have a templated MyObject. We could have:
假设我们有一个模板化的 MyObject。我们可以有:
// - - - - MyObject_forward.hpp - - - -
// This header is included by the code which need to know MyObject
// does exist, but nothing more.
template<typename T>
class MyObject ;
.
.
// - - - - MyObject_declaration.hpp - - - -
// This header is included by the code which need to know how
// MyObject is defined, but nothing more.
#include <MyObject_forward.hpp>
template<typename T>
class MyObject
{
public :
MyObject() ;
// Etc.
} ;
void doSomething() ;
.
.
// - - - - MyObject_implementation.hpp - - - -
// This header is included by the code which need to see
// the implementation of the methods/functions of MyObject,
// but nothing more.
#include <MyObject_declaration.hpp>
template<typename T>
MyObject<T>::MyObject()
{
doSomething() ;
}
// etc.
.
.
// - - - - MyObject_source.cpp - - - -
// This source will have implementation that does not need to
// be shared, which, for templated code, usually means nothing...
#include <MyObject_implementation.hpp>
void doSomething()
{
// etc.
} ;
// etc.
Wow!
哇!
In the "real life", it is usually less complicated. Most code will have only a simple header/source organisation, with some inlined code in the source.
在“现实生活”中,它通常不那么复杂。大多数代码只有一个简单的标题/源代码组织,源代码中有一些内联代码。
But in other cases (templated objects knowing each others), I had to have for each object separate declaration and implementation headers, with an empty source including those headers just to help me see some compilation errors.
但在其他情况下(模板化对象相互了解),我必须为每个对象单独声明和实现标头,包含这些标头的空源只是为了帮助我查看一些编译错误。
Another reason to break down headers into separate headers could be to speed up the compilation, limiting the quantity of symbols parsed to the strict necessary, and avoiding unecessary recompilation of a source who cares only for the forward declaration when an inline method implementation changed.
将标头分解为单独标头的另一个原因可能是加快编译速度,将解析的符号数量限制为严格必要的数量,并避免在内联方法实现更改时只关心前向声明的源进行不必要的重新编译。
Conclusion
结论
You should make your code organization both as simple as possible, and as modular as possible. Put as much as possible in the source file. Only expose in headers what needs to be shared.
您应该使您的代码组织尽可能简单,并尽可能模块化。尽可能多地放在源文件中。只在标题中公开需要共享的内容。
But the day you'll have circular dependancies between templated objects, don't be surprised if your code organization becomes somewhat more "interesting" that the plain header/source organization...
但是当你在模板化对象之间有循环依赖的那一天,如果你的代码组织变得比普通头文件/源代码组织更“有趣”,请不要感到惊讶......
^_^
^_^
回答by Adrien Plisson
in addition to all other answers, i will tell you what you DON'T place in a header file:using
declaration (the most common being using namespace std;
) should not appear in a header file because they pollute the namespace of the source file in which it is included.
除了所有其他答案,我会告诉你什么你不要放在头文件中:using
声明(最常见的是using namespace std;
)不应该出现在头文件中,因为它们会污染包含它的源文件的命名空间.
回答by Pavel Radzivilovsky
What compiles into nothing(zero binary footprint) goes into header file.
什么编译成什么(零二进制足迹)进入头文件。
Variables do not compile into nothing, but type declarations do (coz they only describe how variables behave).
变量不会编译为空,但类型声明会(因为它们只描述变量的行为方式)。
functions do not, but inline functions do (or macros), because they produce code only where called.
函数不会,但内联函数(或宏)会,因为它们只在被调用的地方生成代码。
templates are not code, they are only a recipe for creating code. so they also go in h files.
模板不是代码,它们只是创建代码的一个秘诀。所以他们也进入 h 文件。
回答by Pavel Radzivilovsky
In general, you put declarations in the header file and definitions in the implementation (.cpp) file. The exception to this is templates, where the definition must also go in the header.
通常,您将声明放在头文件中,并将定义放在实现 (.cpp) 文件中。模板是一个例外,其中定义也必须放在标题中。
This question and ones similar to it has been asked frequently on SO - see Why have header files and .cpp files in C++?and C++ Header Files, Code Separationfor example.
这个问题和类似的问题在 SO 上经常被问到 - 请参阅为什么在 C++ 中有头文件和 .cpp 文件?和C++ 头文件,例如代码分离。
回答by Ashish
Mainly header file contain class skeletonor declaration(does not change frequently)
主要是头文件包含类骨架或声明(不经常更改)
and cpp file contains class implementation(changes frequently).
和 cpp 文件包含类实现(经常更改)。
回答by Alexander Gessler
Your class and function declarations plus the documentation, and the definitions for inline functions/methods (although some prefer to put them in separate .inl files).
您的类和函数声明加上文档,以及内联函数/方法的定义(尽管有些人更喜欢将它们放在单独的 .inl 文件中)。
回答by jose
the header file (.h) should be for declarations of classes, structs and its methods, prototypes, etc. The implementation of those objects are made in cpp.
头文件 (.h) 应该用于声明类、结构及其方法、原型等。这些对象的实现是在 cpp 中进行的。
in .h
在.h
class Foo {
int j;
Foo();
Foo(int)
void DoSomething();
}
回答by jk.
I'd expect to see:
我希望看到:
- declarations
- comments
- definitions marked inline
- templates
- 声明
- 注释
- 定义标记为内联
- 模板
the really answer though is what not to put in:
真正的答案是不应该输入的内容:
- definitons (can lead to things being multiply defined)
- using declarations/directives (forces them on anyone including your header, can cause nameclashes)
- 定义(可能导致事物被多重定义)
- 使用声明/指令(将它们强加给任何人,包括您的标题,可能会导致名称冲突)
回答by Khelben
Header (.h)
标题 (.h)
- Macros and includes needed for the interfaces (as few as possible)
- The declaration of the functions and classes
- Documentation of the interface
- Declaration of inline functions/methods, if any
- extern to global variables (if any)
- 接口所需的宏和包含(尽可能少)
- 函数和类的声明
- 接口文档
- 内联函数/方法的声明(如果有)
- 外部到全局变量(如果有的话)
Body (.cpp)
正文 (.cpp)
- Rest of macros and includes
- Include the header of the module
- Definition of functions and methods
- Global variables (if any)
- 其余的宏和包括
- 包含模块的标题
- 函数和方法的定义
- 全局变量(如果有)
As a rule of thumb, you put the "shared" part of the module on the .h (the part that other modules needs to be able to see) and the "not shared" part on the .cpp
根据经验,您将模块的“共享”部分放在 .h(其他模块需要能够看到的部分)和“未共享”部分放在 .cpp
PD: Yes, I've included global variables. I've used them some times and it's important not to define them on the headers, or you'll get a lot of modules, each defining its own variable.
PD:是的,我已经包含了全局变量。我已经使用过它们一些次了,重要的是不要在头文件中定义它们,否则你会得到很多模块,每个模块都定义了自己的变量。
EDIT: Modified after the comment of David
编辑:在大卫的评论后修改