c++ 的 multiple definition of `XXX‘

一、为什么会有多重定义问题?

  • 声明 :指出存储类型,并给出存储单元指定名称
  • 定义 : 分配内存空间,还可为变量指定初始值(对于变量,在内存中开辟空间来保存数据;对于函数,会生成代码,占据一定内存)
  • 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

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值