我试图掌握对c ++的理解,我想知道main.cpp如何知道我构建的类是否在另一个源文件中?编译器是否自动知道我是否在类中包含带有函数参数的头,它会在main.cpp之外的所有源文件中查找它吗?
答案 0 :(得分:6)
简答:它不知道。
答案很长: 我们假设您有以下文件:
#include "A.h"
int main() {
A a;
a.f();
}
class A {
void f();
};
#include "A.h"
A::f()
{
// does something
}
当您调用此命令编译main.cpp
时:
g++ -c main.cpp -o main.o
您的编译器相信您的方法A::f
是在其他地方定义的。但实际上编译器并不知道,它只是信任。
稍后,您调用此命令来编译A.cpp
:
g++ -c A.cpp -o A.o
此时编译器不知道你将如何使用这个类(它不知道main.cpp
还是main.o
的存在。
所有这些"连接魔法"执行此命令时会发生:
g++ main.o A.o -o ./myexe
此时神奇发生在linker
,它发现main.o
正在引用一些名为A
的clase,它在其他地方被定义,然后它找到一个名为{{的文件1}}包含具有相同名称A.o
的类的定义。因此,它发现这个和A
类是相同的,并且正确的链接。
当然,如果你不想要,你不需要执行这三个命令,因为以下内容是等效的:
A
答案 1 :(得分:3)
编译器不知道。因此,您必须手动将所有编译的目标文件添加到将可执行文件链接在一起的命令。
gcc
(以及其他编译器)很乐意使用单个编译器调用来编译多个文件,在这种情况下,它将组合所有编译的对象。或者,您可以编译多个文件,并提供用于链接的目标文件。
但无论如何,您有责任指出所有文件的位置。
答案 2 :(得分:1)
你应该尽早了解C ++的一件事 - 没有什么是自动的: - )
我假设您在IDE中工作,因为使用GNU命令行工具使得无法理解此步骤!
基本上,您的工具链配置为知道要搜索源文件的目录以及搜索头文件的目录。预处理器负责今天使用#include
指令中指示的路径连接头文件(除非您指定标准头,然后搜索可配置的目录列表)。
编译cpp文件时,会生成一个目标文件。这个目标文件可以引用它还不知道的类型 - 链接阶段处理最近的连接。
这是一个例子。
给出以下文件:
SpecialClass.h
#ifndef SPECIAL_CLASS_H_
#define SPECIAL_CLASS_H_
class SpecialClass {
private:
unsigned int x;
public:
SpecialClass();
/** Increment the 'x' value and return it */
int incrementAndReturn();
};
#endif
SpecialClass.cpp
#include "SpecialClass.h"
int SpecialClass::incrementAndReturn() {
return this->x++;
}
SpecialClass::SpecialClass() {
this->x = 0;
}
的main.cpp
#include <iostream>
/**
* By including SpecialClass.h, the compiler can enforce the contract
* outlined in the SpecialClass header. That is, if I try to use a
* method or member that doesn't exist in the SpecialClass type, then
* the compiler can warn me.
*/
#include "SpecialClass.h"
int main(int, char**) {
SpecialClass foo = SpecialClass();
std::cout << foo.incrementAndReturn() << std::endl;
}
我可以逐步构建它,执行编译器似乎只需一步完成的操作:
rdahlgren@athas:~/work/cpp $ g++ -c main.cpp
此时,main.cpp已经编译和汇编,但没有与SpecialClass.cpp中定义的代码的链接 - 它是未链接的。
rdahlgren@athas:~/work/cpp $ g++ -c SpecialClass.cpp
rdahlgren@athas:~/work/cpp $ ls -l
total 20
-rw-r--r-- 1 rdahlgren rdahlgren 410 Feb 26 23:49 main.cpp
-rw-r--r-- 1 rdahlgren rdahlgren 2672 Feb 26 23:50 main.o
-rw-r--r-- 1 rdahlgren rdahlgren 139 Feb 26 23:50 SpecialClass.cpp
-rw-r--r-- 1 rdahlgren rdahlgren 222 Feb 26 23:46 SpecialClass.h
-rw-r--r-- 1 rdahlgren rdahlgren 1448 Feb 26 23:51 SpecialClass.o
你可以在这里看到我现在拥有SpecialClass和main的目标文件(* .o)。这些是编译和汇编的,但是没有链接。
rdahlgren@athas:~/work/cpp $ g++ main.o SpecialClass.o -o main
GCC能够将目标文件链接在一起,如上所示,这会将调用绑定到incrementAndReturn
(等等)。
rdahlgren@athas:~/work/cpp $ ./main
0
为了更好的解释,我建议使用您最喜欢的网络搜索来查找有关“C ++编译步骤”的信息。