在 C++ 中编译和链接多个文件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3820384/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 13:49:29  来源:igfitidea点击:

Compiling & linking multiple files in C++

c++g++compilation

提问by

One of my "non-programmer" friends recently decided to make a C++ program to solve a complicated mechanical problem.

我的一个“非程序员”朋友最近决定编写一个 C++ 程序来解决一个复杂的机械问题。

He wrote each function in a separate .cpp file, then included them all in the main source file, something like this:

他在一个单独的 .cpp 文件中编写了每个函数,然后将它们全部包含在主源文件中,如下所示:

main.cpp:

主.cpp:

#include "function1.cpp"
#include "function2.cpp"
...
int main() 
{
...

}

He then compiled the code, with a single gcc line:

然后他用一个 gcc 行编译了代码

g++ main.cpp    // took about 2 seconds 

Now, I know that this should work, but I'm not sure whether including .cpp files directly into the main program is a good idea. I have seen the following scheme several times, where all the function prototypes go into a header file with the extern keyword, like this:

现在,我知道这应该可行,但我不确定将 .cpp 文件直接包含到主程序中是否是个好主意。我已经多次看到以下方案,其中所有函数原型都放入带有 extern 关键字的头文件中,如下所示:

funcs.h:

函数.h:

extern void function1(..);
extern void function2(..);
...

main.cpp:

主.cpp:

...
#include "funcs.h"
...

& compiling with:

&编译:

g++ -c function1.cpp
g++ -c function2.cpp
...
g++ -c main.cpp
g++ -o final main.o function1.o function2.o ...

I think that this scheme is better (with a makefile, ofcourse). What reasons can I give my friend to convince him so?

我认为这个方案更好(当然有一个 makefile)。我可以给我的朋友什么理由来说服他?

采纳答案by Tony Delroy

The main reason people compile object by object is to save time. High-level localised code changes often only require compilation of one object and a relink, which can be faster. (Compiling too many objects that draw in heaps of headers, or redundantly instantiate the same templates, may actually be slower when a change in common code triggers a fuller recompilation).

人们逐个对象编译的主要原因是为了节省时间。高级本地化代码更改通常只需要编译一个对象和重新链接,这样会更快。(编译太多在头文件堆中绘制的对象,或冗余实例化相同的模板,当公共代码的更改触发更完整的重新编译时,实际上可能会更慢)。

If the project is so small that it can be compiled in 2 seconds, then there's not much actual benefit to the traditional approach, though doing what's expected can save developer time - like yours and ours on here :-). Balancing that, maintaining a makefile takes time too, though you may well end up doing that anyway in order to conveniently capture include directories, libraries, compiler switches etc.

如果项目小到可以在 2 秒内编译完成,那么传统方法并没有多少实际好处,尽管按照预期进行操作可以节省开发人员的时间 - 就像您和我们在这里的时间 :-)。平衡这一点,维护 makefile 也需要时间,尽管您最终可能会这样做,以便方便地捕获包含目录、库、编译器开关等。

Actual implications to written/generated code:

对编写/生成的代码的实际影响:

  • cpp files normally first include their own headers, which provides a sanity check that the header content can be used independently by other client code: put everything together and the namespace is already "contaminated" with includes from earlier headers/implementation files
  • the compiler may optimise better when everything is in one translation unit (+1 for leppie's comment, do do the same...)
  • static non-member variables and anonymous namespaces are private to the translation unit, so including multiple cpps means sharing these around, for better or worse (+1 for Alexander :-))
  • say a cpp files defines a function or variable which is not mentioned in its header and might even be in an anonymous namespace or static: code later in the translation unit could call it freely without needing to hack up their own forward declaration (this is bad - if the function was intended to be called outside its own cpp then it should have been in the header and an externally exposed symbol in its translation unit's object)
  • cpp 文件通常首先包含它们自己的头文件,这提供了一个完整性检查,确保头文件内容可以被其他客户端代码独立使用:将所有内容放在一起,命名空间已经被早期头文件/实现文件中的包含“污染”
  • 当所有内容都在一个翻译单元中时,编译器可能会优化得更好(leppie 的评论为 +1,做同样的事情......)
  • 静态非成员变量和匿名命名空间是翻译单元私有的,因此包含多个 cpp 意味着共享这些,无论好坏(亚历山大 :-) 为+1)
  • 假设一个 cpp 文件定义了一个函数或变量,该函数或变量在其头文件中未提及,甚至可能位于匿名命名空间或静态中:稍后在翻译单元中的代码可以自由调用它,而无需修改自己的前向声明(这很糟糕) - 如果该函数打算在其自己的 cpp 之外调用,那么它应该在标题中并且在其翻译单元的对象中是一个外部公开的符号)

BTW - in C++ your headers can declare functions without explicitly using the externkeyword, and it's normal to do so.

顺便说一句 - 在 C++ 中,您的头文件可以在不显式使用extern关键字的情况下声明函数,这样做很正常。

回答by Alexander Rafferty

The reason for the second style is because each .cpp file can be treated separately, with its own classes, global variables, ect.. without risk of conflict.

第二种风格的原因是因为每个 .cpp 文件都可以单独处理,有自己的类、全局变量等,没有冲突的风险。

It is also easier in IDEs that automatically link all the .cpp files (like MSVC).

在自动链接所有 .cpp 文件(如 MSVC)的 IDE 中也更容易。