在刚学习C++的时候,无法一下子习惯头文件’ .h ’这个东西,因为在C#中,通常函数/变量的声明和实现都是写在一起的,跨.cs文件调用其他类成员时,编译器并不会冒出’ 未找到该变量或函数声明 ’的错误提示,我想,这正是微软在CLR中替我们封装的东西吧….
事情时这样的…
在C++中,如果要将代码变成可执行的.exe,大体需要两步,第一步是逐个编译.cpp源文件;第二步是将变量/函数的声明和定义链接(将当前.cpp文件和被调用的变量/函数定义所在的.cpp文件进行链接)。
从这里可以发现,在进行第一步时,编译器是分别编译每一个.cpp源文件的。显然,这时如果当前源文件中调用了其他源文件中的变量/函数,则编译器就会找不到该变量/函数。于是我们就要在调用变量/函数之前声明该变量/函数,用于告诉编译器说这个变量/函数存在,具体的定义在其他源文件中。这时编译器就知晓了该变量/函数存在,便不会报出' 找不到变量/函数声明的错误 '。而在第二步时,编译器便会先搜索刚刚声明的变量/函数的定义在哪一个.cpp源文件中,找到后,将其和当前源文件链接起来,最终形成可执行程序。
可以想象,如果在每个.cpp中都写上需要调用的变量/函数的声明,那程序员们就要直呼好家伙了。于是乎,大佬就统一规定了一个.h后缀的' 头文件 ',而后把变量/函数的声明写在头文件中。每当源文件中需要用这些声明时,#include "name.h"即可。
基于刚刚分析过的内容,如果头文件中包含了定义,则在每一个引用了该头文件的源文件中就会都定义一次该变量/函数,即导致重复定义。
所以下方关于头文件的规定,也看似理所应当
- 头文件中只允许存在变量/函数的声明,不能存在对其的定义。
BUT!!!上面对头文件的认知,将在你接触到诸如CGAL的HeaderOnly库(他们整个库只包含头文件,不包含源文件)时招到冲击…
为什么将变量/函数定义写在头文件中,却不会造成重复定义呢?在此之前你需要回顾一下inline这个关键字。
头文件中,inline被称为内联函数修饰符,当函数加上inline修饰符后,该函数在被调用时,会自动复制函数定义到调用函数的cpp源文件中,而后,所谓的调用也只是调用当前cpp文件中的函数定义而已,所以不会造成重复定义。
另外,若你在头文件中对类的成员函数进行定义,则编译器会为其自动加上inline修饰符,所以这种情况也不会导致重复定义。对于头文件中定义类模板、函数模板的情况,也同样不会导致重复定义。
现在你也可以写一个HeaderOnly库了:
- 使用inline修饰头文件中的全局函数
- 使用类成员函数
- 使用类模板/函数模板
标签:头文件,函数,定义,C++,源文件,由来,cpp,变量 From: https://www.cnblogs.com/ShawBlack/p/17004370.html