我已经看过(和使用过)这样的情况:
在header.h中:
class point
{
public:
point(xpos, ypos);
int x;
int y;
};
在def.cpp中:
#include"header.h"
point::point(xpos, ypos)
{
x = xpos;
y = ypos;
}
在main.cpp中:
#include"header.h"
int main()
{
point p1(5,6);
return 0;
}
我知道程序是从main执行的,但是编译器如何知道编译.cpp文件的顺序是什么? (特别是如果有多个非主.cpp文件)。
答案 0 :(得分:10)
编译器无关紧要 - 它将每个.cpp文件编译成.obj文件,而.obj文件每个都包含一个缺失符号列表。所以在这种情况下,main.obj说“我缺少point::point
”。
然后链接器的工作是获取所有.obj文件,将它们组合成一个可执行文件,并确保每个.obj文件的缺失符号都可以从另一个文件中获得。 obj文件 - 因此称为“链接器”。
答案 1 :(得分:4)
如果将它们包含在两个不同的cpp文件中,那就没问题了。 如果两次包含相同的标题,则会出现重复定义的错误。
你应该使用包含警戒来规避这一点。
在您的文件之上,在任何代码之前:
#ifndef HEADER_H_ //every header gets it's own name
#define HEADER_H_
在底部:
#endif
答案 2 :(得分:1)
编译顺序无关紧要。所有内容都由编译器编译,编译器使用.h文件来确保至少声明您使用的符号。这是链接器的工作,它在编译器完成后执行,实际上将方法调用与它们的实现匹配。
答案 3 :(得分:1)
编译器不需要知道编译.cpp文件的顺序。
链接器将所有单独编译的.o(从.cpp构建)文件排序,并将所有内容解析为一个可执行文件。
答案 4 :(得分:0)
通常您自己单独编译它们(或使用像make
这样的构建工具)。头文件允许您以任何顺序编译它们。如果你一起编译它们,顺序可能就是你传递给编译器命令的顺序,但它实际上并不重要,它们最终都被链接到一个可执行文件中。
答案 5 :(得分:0)
这是图论应用的一个例子。已编译的模块包含所有代码块的相对偏移量,以及链接器在构造可执行文件时发现依赖关系(图形)。
答案 6 :(得分:-1)
这就是为什么你会在某些头文件的顶部看到#ifndef HEADER_H和#define HEADER_H的原因。例如,每个头文件只包含一个described here的概念。