参考链接如下:
https://stackoverflow.com/questions/1305947/why-does-c-need-a-separate-header-file
叶子一哥:https://blog.csdn.net/abc5382334/article/details/18052757
知乎:https://www.zhihu.com/question/58547318
前言
在学习 learnopengl 时为了日后升级方便,希望将 .h
和 .cpp
分离开,在此过程中遇到了一些疑问,也碰到了一些错误,特意发帖记录一下。
头文件
#include
预编译指令的作用是将所包含的文件全部复制到指令所在的位置
为了防止头文件重复引用,需要将头文件写成下面的形式
#ifndef "XXX_H"
#define "XXX_H"
......
#endif
"重复引用"其实是指一个头文件在同一个cpp文件中被include了多次,例如嵌套引用(b.h中有a.h,c.h引用了a.h和b.h)。
不同的cpp文件是分开编译的,由于C++允许多次声明,多个.cpp文件可以包含同一个头文件,但仍然会全部替换。
头文件重复引用的后果
- 增加编译的工作量,工程大的时候这个问题会非常显著
- 可能会引起错误,例如头文件中定义了全局变量
为什么要分开
C++中只允许一次实现,这意味着如果编译过程中多个.cpp文件中#include了同一个含有函数实现的.h,这个时候链接器会在多个目标文件中找到这个函数的实现,会引发LNK1169的错误:找到一个或多个重定义的符号。
因此为了让函数在多个.cpp中共享,就是在.h文件中声明函数,.cpp文件中实现函数。
测试如下
A.h 中定义了TestFunction()
函数,b.cpp和c.cpp中#include"A.h"
,在main中调用TestFunction()
, 结果如下
特殊情况
可能有的人会有疑问,类的内联函数也是直接将定义写在.h文件中,怎么没有问题?
这是因为C++的类比较特殊,例如多个.cpp中即使有同样的类的声明与实现,即使实现不同也可以通过编译。
按照轮子哥的解释是:C++的类默认是inline的,逻辑上不同的.cpp中的类就应该是相同的。因此编译是没有问题的,只是实现时会挑选不同的实现。
个人遇到的问题
说完了这些,说说我遇到的问题。
在模型加载时用到了 stb_image.h
头文件,这是一个广泛使用的图像处理库。
开始时在 model.h
中包含了 stb_image.h
,然后在 main.cpp
中包含了 model.h
,然后就触发了 LNK1169
错误
由于 stb_image.h
包含了函数的实现,因此在多个 .cpp
中包含此头文件就会出现重定义的问题。
于是更换为在 model.cpp
中包含 stb_image.h
,问题就解决了