C++多文件const变量extern修饰疑问:Dev-C++ C++11实测不符
一、为什么不加extern的const变量能被正常访问?
你的代码里main.cpp直接#include "main3.cpp",这会把main3.cpp的代码原封不动插入到main.cpp中编译,相当于两个文件合并成了同一个编译单元。
C++里const变量默认是内部链接(只能在当前编译单元访问),但因为你用#include把两个cpp合并成一个编译单元,所以main函数里的extern const int a;声明能直接找到同一个单元里的const int a=11;定义,自然能正常输出结果。这并不是因为const变量不需要extern就能跨编译单元访问,只是你的写法跳过了多文件链接的环节。
二、给main3.cpp的a加extern后为什么报错?
当你把main3.cpp里的代码改成extern const int a=11;,再被main.cpp#include后,整个编译单元里会出现:
extern const int a; // main.cpp里的声明 extern const int a=11; // 来自main3.cpp的定义
这时候编译器会认为extern const int a;是一个声明,而后面的extern const int a=11;是一个外部链接的定义。Dev-C++使用的MinGW编译器对同一个编译单元内这类重复的extern声明+定义处理比较严格,因此触发了重复定义的报错。
另外要注意:你不该#include.cpp文件,这是不符合C工程规范的写法。《C Primer》描述的场景是标准的多文件组织方式,正确做法是:
- 新建头文件
main3.h,里面写extern const int a; - main3.cpp里写
const int a=11;(加不加extern都可以,const变量加extern后会变成外部链接,让其他编译单元能访问) - main.cpp只#include "main3.h",而非main3.cpp
这样编译链接时,main.cpp的编译单元通过extern声明找到main3.cpp编译单元里的const变量定义,才是书中说的“const变量需要extern修饰才能跨编译单元访问”的标准场景——因为默认const是内部链接,只有加extern才会变成外部链接,允许其他编译单元访问。
内容的提问来源于stack exchange,提问作者zzz

