为什么需要编译用户定义的文件?C++
Why is compiling user defined files necessary? C++
在做预处理器指令#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
编译)。
您还可以"隐藏"一些细节(特别是在没有说明符private
C 语言中,或者在使用 PIMPL 语言的C++中),因为这些细节隐藏在 cpp 文件中。
另外,在一个非常大的项目中,我不知道编译器是否可以管理如此多的元素(认为它必须具有包含所有名称和标识符的表)。
既然如此,你为什么不把所有东西都放在main.cpp
呢?
请注意,SQLite 使用此方法来提供它的"合并"编译,它将它的所有文件合并到一个文件中进行编译,这使得它更短一些,因为编译器更了解宁愿隐藏的事情。
- .cpp和.h文件中的模板专用化声明
- 为什么两个不同的未命名名称空间可以共存于一个cpp文件中
- 文本文件中的单词链表
- CMake-按正确顺序将项目与C运行时对象文件链接
- 使用新行和不使用新行读取文件
- 在C++程序中输入的文本文件将不起作用,除非文本被复制和粘贴
- 挂起和取消挂起一个文件DLL
- 如何确定我已使用非编码文件到达 EOF?
- 命名空间中具有.h和.cpp文件的类
- 如何使用ndk-build.cmd构建Android.so文件
- 从包含m行的文件中提取n行,必要时(惰性地)重复该文件
- 读取文件并输入到矢量中
- 在C++中查找文件
- c++库的公共头文件中应该包含什么
- 用c++从输入文件中读取另一行
- Cppcheck生成xml转储文件
- 读取文件的最后一行并输入到链接列表时出错
- 无法编译 rtmidi 测试 cmidiin.cpp 文件, 非法指令
- 如何将内容数组写入文本文件?
- C++ Windows 驱动程序MSB3030无法复制该文件,因为它找不到