我正在读一本叫做《跳入C ++》的书,书中有一部分写着:
例如,诸如
的语句#include <iostream>
告诉预处理器将文件iostream的文本直接捕获到当前文件中。每次包含头文件时,它实际上都会被粘贴到文件中,然后编译器才能看到它,并且#include指令将被删除。
因此,据我了解,所有文件都粘贴到一个文件中,因此只剩下一个源文件。但是随后他继续说:
每个源文件都是单独编译的,这意味着目标文件仅包含针对已编译源代码的机器语言。
这表明当进入编译阶段时,源文件仍然是分开的,但是我认为所有文件都已粘贴到一个大文件中。有人可以解释一下,是将所有文件粘贴到一个文件中,还是将它们分开放置,然后再由链接器连接?
答案 0 :(得分:1)
您的最后一点是正确的。 (以下文件结尾对于Linux系统是正确的)
在预处理器完成其工作之后,编译器将每个源文件(.cpp)编译为一个单独的目标文件(.o)。
然后,链接器将它们放到可执行文件,共享库(.so)或静态库(.a)中。
有关更多信息,请查看此问题:How does the compilation/linking process work?
答案 1 :(得分:1)
在C ++中,我们将头文件(.h或.hpp)和代码文件(.cpp)分开 通常在头文件中定义对象结构,并在代码中编写代码以实现其逻辑。
通常在代码文件的顶部包含一组标头
#include <iostream>
#incluie <string>
预处理器将获取这些标头中定义的类的定义,并创建一个包含所有定义的大文件。
代码文件本身将被单独编译为单个.o文件
例如:
song.h
#include <string>
class Song {
public:
std::string getLyrics();
};
person.h
#include "song.h" // Since person sing a Song
class Person {
public:
void sing(Song song);
};
因此,在这种情况下,如果您在代码中执行此操作
main.cpp
#include "person.h"
int main() {
Person person;
Song song;
person.sing(song);
}
预处理器会将您的main.cpp与标头组合成一个大文件。 这就是编译器将看到的。
class string { ...}
class Song {
public:
std::string getLyrics();
};
class Person {
public:
void sing(Song song);
};
int main() {
Person person;
Song song;
person.sing(song);
}
现在,当您将实现添加到.cpp文件中时。 每个实现将单独编译(歌曲,人)。
Song.cpp
#include "song.h" // get the definition of Song
std::string Song::getLyrics() {
return "Every little thing, gonna be alright (bob Marley)\n";
}
Person.cpp
#include "person.h" // get the definition of Person
// Implementation
void Person::sing(Song song) {
std::cout << song.getLyrics();
}
下一步是链接器,它在已编译文件之间链接。
即main.o,person.o和song.o之间的链接,以便main可以创建可以唱歌的人
答案 2 :(得分:1)