为尊重原创以及版权的要求,本文转载自【C++】变量定义在.h头文件导致 multiple definition of 的解决方法和根本原因。在此基础上,写此博文记录知识点并划重点。
C++: multiple definition of 'xxx'
说明
出现这个错误,请你先检查重复定义的变量是否是定义在了.h头文件中,如果是,请您耐心的看完这篇文章,他会告诉你错误的根本原因。
如果你很着急,不想弄清楚原因,请直接按下面的方法更改:
假设重复定义的变量是int a,且你定义在了b.h,想作为全局变量使用,那么:
1.删除b.h中的int a;
2.在b.cpp中加入a的定义int a;
3.在b.h中加入 extern int a;
4.在要使用a的cpp文件中加入#include “b.h”。
一、编译
编译,大家都知道,最后就会产生一个.o
文件,我以前估计就理解到这个水平。于是我常常想不通一个问题,比如MFC的一个大工程,里面有a.cpp,a.h,b.cpp,b.h,
那他们是合在一起编译吗?那互相包含会不会出错?
结论:编译是针对一个文件来说的,比如有a.cpp,a.h,b.cpp,b.h,
他们之间的编译是没有关系的,a.cpp
和a.h
会产生一个a.o
,他的编译和b完全没有关系,同样b.cpp
和b.h
产生的b.o
和a
也没有关系(除了include包含的情况)。
二、链接
我们都知道,ifndef
是为了防止头文件重复包含,比如
a.h:
#include "b.h"
#include "c.h"
b.h:
#include "c.h"
c.h:
这样的话,我们编译a.cpp
肯定会出现问题,因为a.h
里面包含了2次c.h
,而c.h
里面没有加入#ifndef
之类的语句
所以可以将c.h
改为下面的形式:
c.h
#ifndef _C_HEADER
#define _C_HEADER
...
#endif
这样的话,编译a.cpp
就没错了,但是我们要注意,#ifndef
只是针对某一个文件,而不是一个工程。比如你在a.h
里面包含了c.h
,在b.h
里面也包含了c.h
,这样不管你的c.h
有没有加入#ifndef
,你的c.h
文件在a.h
和b.h
当中都会展开,而不是说因为a
和b
是一个工程,所以只展开一次。
三、extern的用法
首先,头文件.h中不适宜定义变量,我们都知道定义全局变量的常规使用方法是在.cpp文件中定义变量,在.h文件中用extern
申明,这是为什么呢?看下面的例子:
比如在MFC的一个大工程中,我想定义一个全局变量int a
,因为所有的文件都包含stdafx.h
,我们考虑写在里面:
stdafx.h:
int a
------------------------
a.cpp:
#include "stdafx.h"
extern int a;
a = 100;
-----------------------
b.cpp:
#include "stdafx.h"
extern int a;
a = 200;
编译没错,但是链接错了!a重复定义。
原因:在编译的时候,由于是一个文件为单位,所以 a.cpp、a.h
被单独编译产生a.o
。这样在链接的时候,由于他包含了stdafx.h
,所以在a.o
中,已经有int a
的定义了。
正确写法:
stdafx.cpp:
int a;
-----------------------
stdafx.h:
extern int a
------------------------
a.cpp:
#include "stdafx.h"
a = 100;
-----------------------
b.cpp:
#include "stdafx.h"
a = 200;
在编译的时候,由于mfc会自己默认编译stdafx.h
和stdafx.cpp
产生stdafx.o
文件,然后我们的a.cpp
编译的时候包括了stdafx.h
,但是stdafx.h
里面只有extern a
,这就说明,我们在下面使用到的a
都是在其他文件中定义的,同样的,b.cpp
编译时,也不会定义a
,所以编译出来的a.o
和b.o
都不包含a的定义。
再链接的时候,由于这是一个工程,所以mfc会把stdafx.o,a.o,b.o
链接在一起,这样我们的a
就定义了一次,在stdafx.o
中。
四、结论
1.编译是针对一个文件来说的,而链接则是针对一个工程所有的.o文件而言的。
2.#ifndef
只是对防止一个文件的重复编译有效。
3.全局变量最好在.cpp文件中定义,在.h文件中加上extern申明,因为在.h文件中定义,容易在链接时造成变量重定义。
4.注意mfc中会自动编译stdafx,并将stdafx.o加入到工程中一起链接。