我有一个小应用程序,全部都在一个文件中。我想将它转换为单独的较小文件。我如何知道如何分离这些内容?代码应该在哪个不可见的边界处分离?
另外,头文件的作用是什么?是为了提前声明方法和类,以便我可以在编译期间链接器包含它们之前在我的代码中使用它们吗?
另外,头文件的作用是什么?是为了提前声明方法和类,以便我可以在编译期间链接器包含它们之前在我的代码中使用它们吗?
头文件应包含类和函数声明。
源文件包含类和函数定义。
通常(即更易读)每个头文件只有一个声明,每个源文件只有一个定义,但是对于小的(即更简单的帮助程序)对象,有时会将它们与相关的更实质性的对象分组。
Menu.h: Contains the Menu declaration.
Menu.cpp: Contains the Menu definition.
头文件包含声明的原因是可以从多个源文件中包含它们,因此每个源文件都具有每个类和函数的完全相同的定义。
可以这样考虑:
如果没有头文件,则需要在每个源文件中拥有类和/或函数声明(不带定义),这意味着每个文件中都有相同的声明副本。因此,如果您修改了一个类,则需要在每个文件中进行相同的修改。通过使用头文件,您可以将声明放在一个地方,因此只需修改一个对象。
首先,您不应该将任何不需要其他文件可见的内容放入头文件中,除非需要它的文件。接下来,让我们定义一些我们需要的东西。
翻译单元
翻译单元是当前正在编译的代码以及直接或间接包含在其中的所有代码。一个翻译单元对应一个.o/.obj文件。
程序
这是将所有.o/.obj文件链接在一起形成的可以执行的二进制文件,用于生成进程。
有不同的翻译单元的主要原因是什么?
现在,如何将代码拆分为不同的翻译单元?答案是没有“所以你这样做!”但您必须根据情况进行考虑。通常很明显,因为您有不同的类,可以将它们放入不同的翻译单元中:
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;
};
声明一些自由函数和对象:
/* 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:
/* 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:
/* so, this is the same as above, just with other classes/files... */
class bar {
public:
bar(); /* constructor */
};
bar.cpp:
/* we need the foo.hpp file, which declares getTheAnswer() */
#include "foo.hpp"
#include "bar.hpp"
bar::bar() {
/* make use of getTheAnswer() */
getTheAnswer();
}
static void help() {
/* .... */
}
希望我能帮到你一点。虽然这是一个很长的答案,但确实存在某些错误。我知道翻译单元的严格定义另有规定(预处理器的输出)。但是,我认为将其包含在上述内容中并没有太大的价值,并且会让事情更加混乱。如果您发现真正的错误,请随时打我 :)
// A.h
class A
{
public:
int fn();
};
// A.cpp
#include "A.h"
int A::fn() {/* implementation of fn */}
//B.cpp
#include "A.h"
void OtherFunction() {
A a;
a.fn();
}
// B.cpp
#include "A.cpp" //DON'T do this!
如果您尝试编译B.cpp,但在链接程序时出现重复定义对象的错误提示 - 这是因为您有多个A的实现副本。