为什么我们需要在编译期间包含C或CPP声明文件而不是像iostream这样的默认库?

时间:2017-04-18 20:55:35

标签: c++ c gcc

如果需要使用我们自己的带有声明的头文件和带有定义的cpp文件来编译CCPP程序,我们需要在编译命令中包含带有定义的cpp文件(参见{ {3}})。但是,当我们编写#include <iostream>时,我们不会在iostream.cpp等编译语句中包含g++ main.cpp iostream.cpp -o main

如果我们编写自定义声明文件,例如hello.hpp带有类声明,hello.cpp带有定义,我们需要在包含g++ main.cpp hello.cpp -o main之后使用hello.hpp编译它main.cpp文件中的标头。这是为什么?

编辑:我们是否可以模仿标准模板库对我们的自定义标头和cpp文件的行为,这样我们所要做的只是包含标头和声明自动获取编译?如果是,那怎么样?如果不是,为什么不呢?

3 个答案:

答案 0 :(得分:5)

标准库正在隐式链接。所以

g++ main.cpp -o main

真的是

g++ main.cpp -o main -lstdc++ -lc

其中libstdc++是c ++标准库,libc是c标准库。其他库需要明确链接(例如libm)。

如果您将编译和链接步骤分开,则会更加清晰:

g++ -c main.cpp -o main.o
g++ -c other.cpp -o other.o
g++ main.o other.o /usr/lib/libstdc++.a /usr/lib/libc.a -o main

这里我们将main()函数定义和其他定义(other.cpp)编译到目标文件中,并将它们与标准库中现有的编译函数/类/变量定义相结合。

请参阅Shared Library Creation上的TLDP页面 Static Library Creation有关定义文件(.c.cpp)如何转换为库的详细信息。

答案 1 :(得分:1)

首先,检查在this post包含<filename>"filename"之间的区别:

  
    

对于#include“filename”,预处理器在与包含该指令的文件相同的目录中进行搜索。这个方法是     通常用于包含程序员定义的头文件。

  
     

对于#include&lt;文件名&GT;预处理器在实现中搜索   依赖方式,通常在预先指定的搜索目录中   编译器/ IDE。此方法通常用于包括标准库   头文件

您包含文件的事实并不意味着您正在编译文件。事实上,通过包含你正在解决包含文件的语法引用,如类声明(在C ++中),常见变量,结构,枚举和函数调用。这将避免代码获取未引用的对象错误,从而破坏编译过程。

使用这些引用编译代码并不意味着编译原始引用的代码。以下面的例子为例:

mycode.cpp包括myclass.hpp,如:

#include "myclass.hpp"

如果引用正确,您可以使用以下命令编译它:

g++ mycode.cpp 

您将拥有mycode.cpp(一个名为mycode.o的目标文件)的编译代码,但不会编译代码myclassmycode.cpp已正确编译,因为它具有对myclass对象/函数/等的引用,但这并不意味着myclass已编译(您还没有对象)档案myclass.o)。

如果您链接编辑mycode.cpp,则会有几个缺少的引用,因为没有myclass已编译的代码。

如果您选择:

g++ mycode.cpp myclass.cpp 

它会生成mycode.omyclass.o的目标文件,以后可以链接在一起。

对于STL库,您只需要引用,因为它们已经编译并且可用于所谓的标准库(已经为您编译的一组对象.o文件)。然后,liker将自动联系或者如果你正确地告诉他那样将它们联系在一起。

我建议您通过compilation -> object files -> link editing -> executable file进程来了解这些步骤,这些步骤仅适用于编译语言。

答案 2 :(得分:1)

您需要了解编译器读取输入文件,然后预处理它们,预处理器替换所有#include语句,以便编译器本身永远不会看到它们。就真正的编译器而言,没有#include语句。然后,编译器将源语言转换为机器代码。编译器为每个输入(c或cpp)文件编写一个目标文件。目标文件中的机器码不能直接执行;它必须与其他代码链接。

最初,程序员会将程序与已经编译成目标文件库的其他目标文件链接起来。多个目标文件静态链接在一起以生成可执行文件,并且可以对许多可执行文件执行此操作。换句话说,许多目标文件中的每一个都可能存在多次,对于许多可执行文件中的每一个都存在一次。这意味着当某些内容发生变化时,有时必须再次链接许多使用相同目标文件的程序。后来的程序员了解到它有助于动态链接到目标文件,这就是动态链接库。

编译程序时,编译器包含链接器链接到其他库的指令,主要是“C运行时”(CRT)。链接可以是静态链接或动态链接。此外,标头提供有关CRT的信息。大多数标准库(std命名空间)实际上都在标题中,例如在“iostream”中,并使用您的程序进行编译。标题中没有的任何内容都在某个CRT库中。

因此,iostream.cpp的等价物可能在您自己的程序中,例如main.cpp,或者已经编译过,并且位于与您的程序链接的CRT库中。