为什么需要编译用户定义的文件?C++

Why is compiling user defined files necessary? C++

本文关键字:文件 C++ 定义 用户 编译 为什么      更新时间:2023-10-16

在做预处理器指令#include <iostream>时,发生的情况类似于文本包含(如复制粘贴)到main.cpp中,你可以用g++ main.cpp编译。你不编译iostream.cpp.

但是用户定义的文件呢?#include "userfile.h"应该在main.cpp中包含类似的文本。那么,如果 main 包含所有必要的代码,为什么我必须编译两个文件(g++ main.cpp userfile.cpp)呢?

iostream这样的"系统库"和用户提供的库之间实际上没有任何区别,除了编译器在处理系统库时会(为了方便起见)留下一些隐含的东西。在这种情况下,它隐式链接到其默认标准库实现。

为了扩展这一点,让我们看看你对g++的第一次调用:

g++ main.cpp

由于g++的默认标准库实现被称为libstdc++,你可以想象这是以下的简写:

g++ -lstdc++ main.cpp

(实际上可能涉及更多的诡计,所以我不保证这个扩展的命令会按原样工作。

以防万一您还不熟悉链接...

编译.cpp时,编译器会生成一个目标文件(通常以.o结尾)。当您有多个.cpp文件时,每个文件都会编译为单独的对象文件。然后必须以某种方式合并它们以生成最终的可执行文件。这种合并称为链接,链接器完成。链接器的工作基本上是匹配不同对象文件中的名称并输出可执行文件。

除了,这太简单了。最终结果不需要是可执行文件,也可以是一个。(我现在会坚持使用静态库,因为我认为它更简单)库是根据以下模式的文件名:lib*.a。无法执行库。相反,库只是将许多.cpp中的一堆功能打包成以后易于使用的形式的便捷方法。您可以将库与您自己的目标文件链接,以生成具有库中的功能以及您自己的代码的可执行文件。

在libstdc++的示例中,如果我们假设您的系统有一个静态库,那就是一个名为libstdc++.a的文件。链接时,我们剥离前导lib和尾随.a(因为所有库都有这个),然后只写stdc++。这就是为什么我们会-lstdc++传递给g++.

库的一个问题(如果我可以这么称呼的话)是它们对编译器没有任何意义,只对链接器有意义。为了使用库,源代码需要#include相应的头文件,以便编译器可以看到其中的定义/声明。

首先,编译速度,这是C和C++等编译语言的繁琐部分。你不需要重新编译(一个缓慢的过程)myclass.cpp,如果你不碰它。您只需重新编译main.cpp如果这是您的修改所在。不要在两个文件程序中思考...考虑更大的程序。(我工作的代码库大约有 100K 行 - 这很小,因为它是一个嵌入式系统 - 完整的编译需要 5-8 分钟;你不能等待每一个微小的更改)。

此外,它使它更加模块化,这意味着即使被两个不同的程序使用,您也可以只编译一次文件。如果你有一个通过网络发送MyClass对象的客户端-服务器,那么两者都需要myclass.cpp(myclass.o编译)。

您还可以"隐藏"一些细节(特别是在没有说明符privateC 语言中,或者在使用 PIMPL 语言的C++中),因为这些细节隐藏在 cpp 文件中。

另外,在一个非常大的项目中,我不知道编译器是否可以管理如此多的元素(认为它必须具有包含所有名称和标识符的表)。

既然如此,你为什么不把所有东西都放在main.cpp呢?

请注意,SQLite 使用此方法来提供它的"合并"编译,它将它的所有文件合并到一个文件中进行编译,这使得它更短一些,因为编译器更了解宁愿隐藏的事情。