重复声明不报错,重复定义导致链接失败;头文件中禁放非const变量定义,const变量默认内部链接可放头文件,类静态成员需在.cpp中定义。

重复声明不会报错,重复定义会链接失败
编译阶段通常不拦重复声明,但链接时一旦发现同一个符号(比如变量名 counter)在多个 .o 文件里都分配了内存空间,ld 就会报 multiple definition of 'counter'。这是最直接的区分信号。
典型现象:
- 只改头文件、加了
#ifndef还是报错 → 很可能是头文件里写了定义(比如int counter = 0;),不是声明 - 错误信息里带
.o文件名和段名(如.bss+0x0)→ 链接阶段问题,基本锁定为重复定义 - 编译单个
.cpp没问题,一链接就崩 → 定义跨了多个源文件
extern int x; 是声明,int x = 1; 是定义
关键看有没有分配存储空间、是否带初始化。即使用了 extern,只要赋了值,就是定义:
-
extern int x;✅ 声明(告诉编译器“x 在别处”) -
int x;✅ 定义(未初始化,但分配了内存) -
int x = 42;✅ 定义(初始化 + 分配内存) -
extern int x = 42;❌ 既是声明又是定义(C++ 中允许,但会导致多文件包含时重复定义)
头文件里绝对不要写 int x = 0; 或 int x; —— 这会让每个包含它的 .cpp 都生成一份 x 的副本,链接时必然冲突。
立即学习“C++免费学习笔记(深入)”;
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
const 全局变量在头文件里算“内部链接”,可以例外
普通变量不行,但 const 变量默认有 static 链接属性,所以:
-
const int MAX_SIZE = 100;放头文件里 → 每个.cpp都有一份副本,但互不干扰,不会链接冲突 -
extern const int MAX_SIZE = 100;→ 强制变成外部链接,反而可能引发重复定义 - 如果真需要跨文件共享 const 变量,应该:
头文件中写extern const int MAX_SIZE;,源文件中写const int MAX_SIZE = 100;
注意:这个规则对 constexpr 同样适用,且更安全。
类内静态成员变量必须分离声明和定义
类定义里写 static int count; 是声明;真正分配内存必须在某个 .cpp 里写 int MyClass::count = 0;:
- 只在头文件里写
static int count = 0;→ C++17 前是错误(重复定义),C++17 起用inline才允许 - 写成
static constexpr int count = 0;→ 可以放头文件,没问题 - 漏掉
.cpp中的定义 → 链接时报undefined reference to 'MyClass::count',这是“没定义”,不是“重复定义”
最容易被忽略的是:模板类里的静态成员,哪怕加了 inline,也得确保只有一个翻译单元实际实例化它,否则照样撞上 ODR(单一定义规则)。

















