lee-romantic 's Blog
Everything is OK!
Toggle navigation
lee-romantic 's Blog
主页
About Me
归档
标签
C++ 头文件被多个cpp包含导致的重定义问题
2025-07-09 22:24:36
1
0
0
lee-romantic
# 某个源文件多次包含同一个头文件 某个源文件多次包含同一个头文件时,如果头文件中有定义语句,那么不管是什么东西的定义,都可能会产生重定义错误。这种情况是很常见的问题,通常可以使用宏定义保护避免: ``` #ifndef A_H #define A_H /* 这里写真正的头文件 */ #endif ``` 使用`#program once`也可以,二者区别参考[#program once 和 #ifndef](https://blog.csdn.net/markey1/article/details/122742882)。 # 多个源文件包含了同一个头文件 ## 错误原因 但是多个源文件包含同一个头文件,宏定义或者`#program once`也无法进行避免了,一个本人真实遇到的例子是:。 在`m_settings.h`中: ``` #ifndef _M_SETTINGS_H #define _M_SETTINGS_H ... namespace setting_ns { int aa = 10; QStringList splitArgs(const QString &s, int idx){ // splitArgs函数的定义 } // 这里因为aa和splitArgs的定义在头文件内,要么改成const和inline,要么将定义放到.cpp中以避免可能的重定义报错 } #endif ``` 在`qsetting_obj.h`中,包含了`m_settings.h`: ``` ··· #include "header/m_settings.h" ``` 很不幸,在`main.cpp`中,我又同时`include`包含了`qsetting_obj.h`和`m_settings.h`,导致变量`aa`和`splitArgs`的`multiple definition of`重定义报错,哪怕这里套上命名空间都没用,因为是重复包含导致的和自身重复,而不是和外部的别的符号重复。 按道理来说,使用 #ifdef 等条件编译语句避免头文件在同环境被重复包含,由于`#ifndef ...`宏定义的保护,只会`include`一次`m_settings.h`。 但是, 请注意"同环境"这个限定,include虽然只是是简单的将文件复制进cpp吗,当多个cpp源文件包含了同一个头文件时,如果头文件中有某个局部变量或者非内联(`inline`)函数的定义,那么相当于每个源文件都把该局部变量或者非内联函数定义了一次,而它们(局部变量或者非内联函数)在这种情况下默认又是全局的,那么自然会导致重定义错误。 ## 如何避免 我们应当**`避免在头文件中定义局部变量或者非内联(inline)函数, 实在是需要,应当将局部变量或者非内联函数的定义放在.cpp中`**。由于编译器会将类,内联函数以及`C++ const`变量默认视为定义它们的源文件所私有,因此它们(类,内联函数以及`const`变量)可以定义在头文件中。 实在是想在头文件中声明局部变量(全局变量可用extern关键字,但在头文件中也只能是声明,然后在某个cpp、c文件中定义,比如"extern double Pi"),inline关键字也可以解决这个问题(C++17开始也支持[inline变量](https://www.51cto.com/article/804492.html)了),但是真没必要这么做。 经测试,`static`变量也可以放在头文件中,因为`static` 可以修饰函数和变量,静态变量只初始化一次,存储在静态区,并且可以将其对其他源文件隐藏起来,从而避免重定义命名冲突。对于函数来讲,`static` 的作用仅限于该隐藏功能。全局变量也存储在静态数据区。在静态数据区,内存中所有的字节默认值都是`0x00`。 参考[`static`变量](https://blog.csdn.net/weixin_45031801/article/details/134215425) 另外,C++中const变量和类,也是可以的(但是C语言中不行,其const变量仍然是公有链接属性)。 总得来说,C++的const变量,类,inline函数(C++17 inline变量也可以), static变量和函数可以在.h中定义,[参考](https://blog.csdn.net/stpeace/article/details/44468277) ## 强弱符号 在`C++`中,全局变量默认被视为强符号,因此在多个源文件包含同一个头文件并定义全局变量时,连接器可能会报错。而在`C`语言中,多个`int i`的声明不会被认为是错误,而是根据是否初始化来判断强弱符号。这解释了为什么在`C++`中多个源文件包含同一个头文件可能导致问题,而在C语言中可能不会出现相同的问题。参考[C强符号弱符号](https://zhuanlan.zhihu.com/p/674885990) 参考链接: https://www.cnblogs.com/muchen/p/6138110.html https://baijiahao.baidu.com/s?id=1640452050886267027&wfr=spider&for=pc https://www.51cto.com/article/804492.html
上一篇:
QA_Training
下一篇:
点云数据格式bin转为pcd的问题
0
赞
1 人读过
新浪微博
微信
腾讯微博
QQ空间
人人网
提交评论
立即登录
, 发表评论.
没有帐号?
立即注册
0
条评论
More...
文档导航
没有帐号? 立即注册