2017-05-21 34 views
0

为什么在预处理步骤中,主文件中的#include仅被替换为相关头文件的内容(而不是函数定义(.cpp文件))?源代码构建混淆(预处理和链接)

我认为在这一步它应该首先进入头文件,并用相关的.cpp文件的内容替换#includes,然后回去替换主文件中的#includes与一切,从而否定任何链接(一个巨大的文件与一切)的需要。为什么不会发生这种情况?

+2

因为你每次都要编译许多次代码。每次都会重新编译一个没有改变的CPP文件。使用预编译的库加快编译速度是不可能的。 – user4581301

+1

另外,正常的方法可以让你使用你甚至没有源代码的函数。 –

+0

“...它们的相关.cpp文件”。在C++语言中, 中没有这样的关联。你可以调用一个头文件'iostream'(就像 C++标准库所做的那样),并且在任意数量的源文件中定义被声明为 的东西,称为任何你喜欢的东西。 –

回答

0

为什么在预处理步骤中,主文件中的#include仅被替换为相关头文件的内容(而不是函数定义(.cpp文件))?

简而言之,头文件是您告诉预处理器的唯一文件。它不能假定源文件的名称,因为对于任何给定的头文件可能有许多源文件。你可能会想:“嘿,我为什么不只是包括的源文件?”我在这里告诉你不!坏!另外,谁说你可以首先访问源文件?

编译器知道并编译所有源文件的唯一方法是让编译器传递每个源文件,让它们编译成对象,并将这些对象链接到一个库或可执行文件中。

0

compiling and linking之间有很大的区别:

预处理器,预编译时和编译时间:

预处理器检查#符号,并与相关的内容如替代它:

#include <iostream> // the content will be replaced here and this line will be removed 

所以iostream的内容将被添加到上面。

EG2:

#define PI 3.14 // wherever PI is used in your source file the macro will be expanded replacing each PI with the constant value 3.14 

编译器仅检查syntax errors,函数的原型... and doesn't care about the body of functions, resulting in an的obj file`。

链接时:

链接器链接这些obj files有关库,在这非常时期functions called必须有一个定义;没有定义将在链接时错误中发布。

0

为什么它不会发生这种情况?

历史和经验的程序员的期望,以及他们与大项目的经验(见最后陈述,下同)


我认为,在这个步骤中,应该首先进入头 文件,并与他们相关的 .cpp文件的内容替换#包括有...

如果ACCE对于使用C++进行编码的工作,贵公司将为您提供编码标准,详细说明您将要遵循的指导方针或规则,或者在您偏离它们时面临捍卫您的选择的问题。

您现在可能需要一些时间才能查看可用的编码标准。例如,尝试学习Google C++风格指南(我不特别喜欢或不喜欢这个,它只是很容易记住)。一个简单的谷歌搜索也可以找到几种编码标准。添加'为什么符合编码标准?'到您的搜索可能会提供一些信息。


否定任何链接的需求(一切一个巨大的文件)。

注意:这种方法不能消除与编译器工具或第三方提供的库的链接。我经常使用-lrt,-pthread和一些时间-lncurses,-lgmp,-lgmpxx等。

现在,作为一个实验,您可以手动实现巨型文件方法(我经常为我做的较小的试用和私人工具的开发)。

试想一下:

如果main.cc有:

#include "./Foo.hh" // << note .hh file 

int main(int argc, char* argv[]) 
{ 
    Foo foo(argc, argv); 

    foo.show(); 
... 

和Foo.cc具有

#include "./Foo.hh" // << note .hh file 

// Foo implementation 

这个普通模式(不,不是模式书模式),并且会要求你将Foo.o和main连接在一起,这对于小构建来说足够小,但还有更多的事情要做。

的“small'岬允许您使用的#include创建你的‘一切’容易一个巨大的文件:

变化主要以

#include "./Foo.cc" // << note .cc also pulls in .hh 
         // (prepare for blow back on this idea)  

int main(int argc, char* argv[]) 
{ 
    Foo foo(argc, argv); 

    foo.show(); 
... 

编译器看到所有的代码在一个编制单位。没有链接本地.o的需要(但仍然库链接)。


请注意,我不建议这样做。为什么?

可能主要原因是我的很多工具都有100个对象(即100个.cc文件)。那个单一的“巨人”档案可能相当庞大。

对于大多数开发流失(即早期错误修复),只有一个或两个.cc文件获取更改。重新编译所有源代码可能会浪费大量时间和编译器的时间。

替代方案是什么经验的开发人员已经了解到:

A)编制的.cc的小得多的数量已经改变了(也许是一个或两个),

B),然后与连接它们?没有改变的其他.o's的100年代更快地构建。

您的工作效率的一个关键是最大限度地减少编辑 - 编译 - 调试时间。 A和B以及一个好的编辑器对这个迭代很重要。