头文件如何提供函数定义

How are function definitions provided by the header file

我有三个文件 - main.cpp、file1.cpp 和 headerFile.h。

file1 是-

#include<iostream>
using namespace std;
void function1(){
    cout<<"this is function1 from file1"<<endl;

}

headerFile.h 是-

#ifndef HEADERFILE_H_
#define HEADERFILE_H_

void function1();

#endif /* HEADERFILE_H_ */

main.cpp 文件是-

#include<iostream>
using namespace std;
#include "headerFile.h"

int main(){

function1();

    cout<<"this is main function from mainFile"<<endl;
    return 0;
}

在此阶段之前,function1() 对 main.cpp 文件是未知的。
现在人们说当编译器在主文件中遇到#include "headerFile.h"时,它只是将headerFile.h的代码复制到主文件中,
因此主文件变为-

#include<iostream>
using namespace std;


#ifndef HEADERFILE_H_
#define HEADERFILE_H_

void function1();

#endif /* HEADERFILE_H_ */


int main(){

function1();

    cout<<"this is main function from mainFile"<<endl;
    return 0;
}

现在,编译器仍然不知道这里的 function1() 定义。这个定义是如何解决的?请解释一下。

在编译 main.cpp 时,编译器仍然不知道函数定义(它变成 main.obj 或类似的,具体取决于 compiler/platform)。它只需要知道由 headerFile.h 中的声明提供的该函数的签名(它的名称、return 值、参数)。在编译后的目标文件中会写(用机器语言)。

here, the user is calling some function1, please, linker, find its address and insert it there.

现在,当您将 file1.cpp 编译成 file1.obj 时,file1.obj 将包含已编译的 function1.

最后,当您 link 将这两个文件转换为可执行文件(或库)时,linker 将解决仅调用已声明(但未定义)函数的所有问题。所以引用的部分会变成

here, the user is calling the function1, and it's definition is located at 0x0123ABC.

但是,如果您提供带有无法解析的函数调用的对象文件,您将收到 linker 错误(类似于)

/tmp/ccwckoGI.o: In function main:
/home/user/file.cpp:5: undefined reference to foo()

头文件 - headerFile.h 包含函数的声明,并且必须附有源文件 - headerFile.cpp

现在,当您执行 #include "headerFile.h" 时,函数的声明就已知了,因此可以编译代码。此时 - 当编译 main.cpp 时,main.obj 没有函数的定义。在编译每个 .cpp 文件并生成 .obj 个文件后,它们会链接在一起,由 linker 为您提供程序。

// headerFile.h

#ifndef HEADERFILE_H_
#define HEADERFILE_H_

// add extern to tell the compiler that this function definition is in other file, yes it is in file1, complied into file1.obj
extern void function1();

#endif /* HEADERFILE_H_ */

链接器将在 file1.obj 中找到 function1() 的定义。你当然应该添加到你的构建命令中。