C++ 头文件,代码分离
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/280033/
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
C++ Header Files, Code Separation
提问by
I am new to C++ and I had a few general questions about code separation. I have currently built a small application, all in one file. What I want to do now is convert this into separate files such that they contain similar code or whatnot. My real question right now is, how do I know how to separate things? What is the invisible margin that code should be separated at?
我是 C++ 的新手,我有一些关于代码分离的一般问题。我目前已经在一个文件中构建了一个小应用程序。我现在想要做的是将其转换为单独的文件,以便它们包含类似的代码或诸如此类的内容。我现在真正的问题是,我怎么知道如何分离事物?代码应该分隔的隐形边距是多少?
Also, what's the point of header files? Is it to forward declare methods and classes so I can use them in my code before they are included by the linker during compilation?
另外,头文件有什么意义?是否转发声明方法和类,以便我可以在编译期间链接器包含它们之前在我的代码中使用它们?
Any insight into methods or best practises would be great, thanks!
任何对方法或最佳实践的见解都会很棒,谢谢!
回答by Martin York
Header files should contain class and function declarations.
头文件应该包含类和函数声明。
Source files contain class and function definitions.
源文件包含类和函数定义。
It is standard practice (i.e. read easier) to have one declaration per header file and one definition per source file, though for small (read simpler helper) objects you sometimes group them with related more substantial objects.
标准做法(即阅读更容易)每个头文件有一个声明,每个源文件有一个定义,但对于小的(阅读更简单的帮助程序)对象,您有时会将它们与相关的更重要的对象分组。
Example: Class Menu
示例:班级菜单
Menu.h: Contains the Menu declaration.
Menu.cpp: Contains the Menu definition.
The reason header files contain the declarations is so that you can include them from multiple source files and thus each source file has exactly the same definition of each class and function.
头文件包含声明的原因是您可以从多个源文件中包含它们,因此每个源文件对每个类和函数具有完全相同的定义。
Consider it this way:
If you did not have header files then you would need to have the class and/or function declarations (without) definitions in every source file, this means a copy of the same declaration in every file. Thus if you modify a class you need to make the same modification in every file. By the use of a header file you have the declaration in one place and thus only one object to modify.
这样考虑:
如果您没有头文件,那么您需要在每个源文件中都有类和/或函数声明(没有)定义,这意味着每个文件中都有相同声明的副本。因此,如果您修改一个类,您需要在每个文件中进行相同的修改。通过使用头文件,您可以将声明放在一处,因此只有一个对象需要修改。
回答by Johannes Schaub - litb
First, you should not put anything into headers that is not needed to be visible by any other file, other than the one that needs it. Then, let's define something we need below.
首先,除了需要的文件外,您不应将任何其他文件不需要的任何内容放入标题中。然后,让我们在下面定义一些我们需要的东西。
Translation Unit
A Translation Unit is the current code being compiled, and all the code included by it, directly or indirectly. One Translation unit translates to one .o / .obj file.
Program
That's all your .o / .obj files linked together into one binary file that can be executed to form a process.
翻译组
翻译单元是当前正在编译的代码,以及它直接或间接包含的所有代码。一个翻译单元翻译成一个 .o / .obj 文件。
程序
这就是您所有的 .o / .obj 文件链接到一个二进制文件中,该文件可以执行以形成一个进程。
What are the main points of having different translation units?
拥有不同翻译单元的要点是什么?
- Reduce dependencies, so that if you change one method of one class, you don't have to recompile all the code of your program, but only the affected translation unit. An
- Reduce possible name clashes by having translation unit local names, that are not visible by other translation unit when linking them together.
- 减少依赖,这样如果你改变一个类的一个方法,你就不必重新编译你程序的所有代码,而只需要重新编译受影响的翻译单元。一个
- 通过使用翻译单元本地名称来减少可能的名称冲突,这些名称在将它们链接在一起时其他翻译单元不可见。
Now, how can you split your code into different translation units? The answer is there is no "so you do it!", but you have to consider it on a case-by-case basis. It's often clear, since you have different classes, which can and should be put in different translation units:
现在,如何将代码拆分为不同的翻译单元?答案是没有“所以你做吧!”,但你必须逐案考虑。通常很清楚,因为你有不同的类,它们可以而且应该放在不同的翻译单元中:
foo.hpp:
foo.hpp:
/* Only declaration of class foo we define below. Note that a declaration
* is not a definition. But a definition is always also a declaration */
class foo;
/* definition of a class foo. the same class definition can appear
in multiple translation units provided that each definition is the same
basicially, but only once per translation unit. This too is called the
"One Definition Rule" (ODR). */
class foo {
/* declaration of a member function doit */
void doit();
/* definition of an data-member age */
int age;
};
Declare some free functions and objects:
声明一些免费的函数和对象:
/* if you have translation unit non-local (with so-called extern linkage)
names, you declare them here, so other translation units can include
your file "foo.hpp" and use them. */
void getTheAnswer();
/* to avoid that the following is a definition of a object, you put "extern"
in front of it. */
extern int answerCheat;
foo.cpp:
foo.cpp:
/* include the header of it */
#include "foo.hpp"
/* definition of the member function doit */
void foo::doit() {
/* ... */
}
/* definition of a translation unit local name. preferred way in c++. */
namespace {
void help() {
/* ... */
}
}
void getTheAnswer() {
/* let's call our helper function */
help();
/* ... */
}
/* define answerCheat. non-const objects are translation unit nonlocal
by default */
int answerCheat = 42;
bar.hpp:
bar.hpp:
/* so, this is the same as above, just with other classes/files... */
class bar {
public:
bar(); /* constructor */
};
bar.cpp:
bar.cpp:
/* we need the foo.hpp file, which declares getTheAnswer() */
#include "foo.hpp"
#include "bar.hpp"
bar::bar() {
/* make use of getTheAnswer() */
getTheAnswer();
}
Please note that names within an anonymous namespace (as above) do not clash since they appear to be translation unit local. in reality they are not, they just have unique names so that they do not clash. if you really want (there is little reason to) translation unit local names (for example because of compatibility with c so C code can call your function) you can do it like this:
请注意匿名命名空间中的名称(如上)不会冲突,因为它们似乎是本地翻译单元。实际上它们不是,它们只是具有唯一的名称,因此它们不会发生冲突。如果您真的想要(几乎没有理由)翻译单元本地名称(例如因为与 c 兼容,因此 C 代码可以调用您的函数),您可以这样做:
static void help() {
/* .... */
}
The ODR also says that you cannot have more than one definition of any object or non-inline function in one program (classes are types, not objects, so it doesn't apply to them). So you have to watch out not to put non-inline functions into headers, or not putting objects like "int foo;" in headers. That will cause linker errors then when the linker tries to link the translation units including those headers together.
ODR 还表示,在一个程序中不能有多个对象或非内联函数的定义(类是类型,而不是对象,因此不适用于它们)。因此,您必须注意不要将非内联函数放入标头中,或者不要将诸如“int foo;”之类的对象放入其中。在标题中。这将导致链接器错误,然后当链接器尝试将包含这些标头的翻译单元链接在一起时。
I hope i could help you a bit. Now that was a long answer, there are indeed errors somewhere. I know that a translation unit strictly is defined another way (output of the pre-processor). But i think it would not add big value to include that into the above, and it would confuse the matter. Please feel free to slap me if you find real bugs :)
我希望我能帮到你一点。现在这是一个很长的答案,确实在某处存在错误。我知道翻译单元是用另一种方式严格定义的(预处理器的输出)。但是我认为将其包含在上述内容中不会增加很大的价值,并且会混淆问题。如果您发现真正的错误,请随时给我打耳光:)
回答by David Dibben
Deciding how to separate your code into different classes/functions is one of main tasks of programing. There are many different guidelines on how to do this and I would recommend reading some tutorials on C++ and Object Oriented Design to get you started.
决定如何将代码分成不同的类/函数是编程的主要任务之一。关于如何执行此操作有许多不同的指南,我建议您阅读一些有关 C++ 和面向对象设计的教程以帮助您入门。
Some basic guidelines will be
一些基本准则将是
- Put things together which are used together
- Create classes for domain objects (eg files, collections etc)
- 把一起用的东西放在一起
- 为域对象(例如文件、集合等)创建类
Header files allow you to declare a class or function and then use it in several different source files. For example, if you declare a class in a header file
头文件允许您声明一个类或函数,然后在几个不同的源文件中使用它。例如,如果您在头文件中声明一个类
// A.h
class A
{
public:
int fn();
};
You can then use this class in several source files:
然后,您可以在多个源文件中使用此类:
// A.cpp
#include "A.h"
int A::fn() {/* implementation of fn */}
//B.cpp
#include "A.h"
void OtherFunction() {
A a;
a.fn();
}
So header files enable you to separate the declaration from the implementation. If you were to put everything (declaration and implementation) in a source file (eg A.cpp) then try to include that in a second file, eg
因此,头文件使您能够将声明与实现分开。如果您要将所有内容(声明和实现)放在源文件(例如 A.cpp)中,请尝试将其包含在第二个文件中,例如
// B.cpp
#include "A.cpp" //DON'T do this!
Then you could compile B.cpp but when you try to link your program the linker will complain that you have multiply defined objects - this is because you have multiple copies of the implementation of A.
然后你可以编译 B.cpp 但是当你尝试链接你的程序时,链接器会抱怨你有多个定义的对象 - 这是因为你有多个 A 的实现副本。
回答by Elroy
Suggestion: 1. Have a design ready for your application now. 2. Based on the design, create necessary objects that interact with each other. 3. Refactor or completely change the existing code to suit the newly created design.
建议: 1. 现在就为您的应用准备好设计。2. 根据设计,创建必要的相互交互的对象。3. 重构或完全更改现有代码以适应新创建的设计。
Header files provide an interface to the other classes that might use it's functionality.
头文件为可能使用其功能的其他类提供了一个接口。