头文件如何提供函数定义
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() 的定义。你当然应该添加到你的构建命令中。
我有三个文件 - 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 tofoo()
头文件 - 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() 的定义。你当然应该添加到你的构建命令中。