函数extern声明与引入.h文件的对比及相关疑问
extern声明函数与#include头文件的对比及代码问题解答
一、extern声明相比#include头文件的优势
- 减少编译开销:
#include会把整个头文件内容原封不动拷贝到当前源文件中,若头文件体积大、包含大量无关内容(比如其他函数声明、宏、类型定义),会增加预处理器处理时间,扩大编译规模。而extern仅声明目标函数的原型,不会引入额外内容,能有效缩短编译耗时。 - 降低编译依赖:如果头文件发生非函数原型的修改(比如新增宏、修改typedef),所有
#include该头文件的源文件都需要重新编译;但用extern声明的话,只要函数参数、返回值等原型未变,当前源文件无需重新编译。 - 避免命名冲突:头文件可能包含大量全局符号(宏、枚举、全局变量声明等),
#include后这些符号会进入当前文件作用域,容易引发命名冲突。extern只引入目标函数的声明,能规避这类问题。
关于内存占用的误区:这种写法不会减少运行时内存占用。函数的运行时内存占用由其实现逻辑决定,和声明方式无关。两者的差异仅体现在编译阶段,而非运行阶段。
二、给定代码结构的问题分析
先看你的代码:
FileA.cpp:
extern void foo(); ... void AnotherFunction() { ... foo(); ... }FileB.h:
extern "C" void foo() { //Something something }
1. 直接#include FileB.h是否可行?
绝对不可行。因为FileB.h里直接写了foo()的函数定义(带有函数体),#include这个头文件后,函数定义会被拷贝到每个包含它的源文件中。当多个源文件都#include该头文件时,链接阶段会报多重定义错误——每个目标文件里都有一份foo()的实现,链接器无法确定使用哪一份。
2. 正确的做法是什么?
有两种合理方案:
- 方案一:修改头文件结构(推荐)
把函数声明和定义分离:- FileB.h:仅保留声明
extern "C" void foo(); - FileB.cpp:存放函数定义
#include "FileB.h" void foo() { //Something something }
#include "FileB.h"即可,这样既保证了声明的一致性,又不会出现多重定义问题。 - FileB.h:仅保留声明
- 方案二:在FileA.cpp里使用匹配的extern声明
由于foo()是extern "C"的,FileA.cpp里的声明需要匹配:
这样能正确链接到extern "C" void foo();FileB.h里的foo()(但依然不建议在头文件中写函数定义,这属于不良编码习惯)。
总结:无论哪种情况,都不应直接#include包含函数定义的头文件。推荐采用声明与定义分离的方式,再通过#include头文件获取函数声明,这比单独写extern更可靠——头文件里的声明是唯一的,能避免手动写extern时出现原型不匹配的错误。
内容的提问来源于stack exchange,提问作者Houst
相关产品推荐
相关产品推荐

