一、为什么会有多重定义问题?
- 声明 :指出存储类型,并给出存储单元指定名称
- 定义 : 分配内存空间,还可为变量指定初始值(对于变量,在内存中开辟空间来保存数据;对于函数,会生成代码,占据一定内存)
- extern 关键字: 如果想声明一个变量而非定义它,就在变量名前加extern 关键字,而且不要显示初始化变量.(extern 语句如果包含了初始值,就变成定义了)
- 在函数被调用之前必须先有函数原型(函数声明),函数定义可以放在调用函数的后面
extern double i ; //声明i而非定义i
int i; //声明并定义i
! 变量能且只能被定义一次,但可以被多次声明
- 因为c++语言支持分离式编译,允许程序分割为若干个文件,每个文件可独立编译。如果多个文件共享一个变量,就必须将声明和定义分离,且变量的定义必须出现在且只能出现在一个文件中,否则就出现了重复定义问题。
原文链接:https://blog.csdn.net/mantis_1984/article/details/53571758
- 函数声明和定义也是如此。如果函数定义在a.h,且a.h 被多个文件包含,那么就会报重定义错误
三种可以把定义放在头文件的
- 值在编译时就已知的const 变量的定义
- 类的定义可以放在头文件
- inline函数(内联函数的声明和定义需要在同一文件,否则无法通过编译。编译器需要将内联函数插入到调用位置)
- 模板函数,编译时需要根据函数模板实例化对应函数
-
二、 一些错误情景
1、头文件忘记加条件编译
#pragma once
或者
#ifndef HEAD_H
#define HEAD_H
...
#endif
这里补充一下,加条件编译只是防止同一个cpp文件包含同一个头文件多次,在独立编译时生成对应的符号表。可能就会发生两个cpp文件都有同一个全局变量的定义,到链接时双方一交流,发现重复,就报错了。
2、类的静态变量在头文件定义
比如下面的A:count在a.h定义,若a.h被多个文件包含,就会重定义
a.h
#pragma once
#include <iostream>
using namespace std;
class A{
public :
static int count ;
void inc();
};
int A::count = 0;
解决办法:
把a.h里对静态变量的定义放在cpp文件中,.h不要定义
a.cpp 实现
#include "a.h"
int A::count = 0;//定义
void A::inc(){
count++;
}
3、全局变量在.h文件定义
原理同2差不多,解决办法是在a.cpp定义,然后a.h文件 extern 声明,然后其他需要使用全局变量的.c文件中包含a.h文件即可.
//a.h
extern int aa;
//a.cpp
int aa = 10;
之前还看到过一个解决办法时加static关键字,后来又查了下,在.h 文件
//a.h
static int aa = 3;
相当于把aa的作用域局限于定义它的源文件中,其他源文件不能访问。换句话说,如果b.cpp 和d.cpp都包含了a.h, 相当于每一个cpp文件定义了一个新的单独的变量aa,彼此空间独立,互不干扰,并不是真正的空间变量。
4、待补充
三、参考链接
https://zhuanlan.zhihu.com/p/74528787
https://zhuanlan.zhihu.com/p/38588925
https://blog.csdn.net/mantis_1984/article/details/53571758