error LNK2005:xxx已在xxx.obj中定义fatal error LNK1169: 找到一个或多个多重定义的符号

        工程中有一个can.cpp文件内定义了很多变量和函数,就想把这部分定义搬出来新建一个vars.cpp文件,然后再将vars.cpp包含进can.cpp中即#include“vars.cpp”,编译的时候出现了很多错误。error LNK2005:xxx已在can.obj中定义fatal error LNK1169: 找到一个或多个多重定义的符号。在工程文件夹的debug目录下发现vars.cpp生成了一个vars.obj文件。原来的can.cpp文件也生成了一个同名的can.obj文件。单独的.cpp或.h文件会生成对应的.obj文件,每一对同名的.h和.cpp文件会生成一个.obj文件。原来将vars.cpp包含进can.cpp中时,#include“vars.cpp”作用是将vars.cpp中的所有代码原封不动的抄到can.cpp中,就是预处理时将vars.cpp中的内容展开到can.cpp中。vars.cpp会生成一个vars.obj,can.cpp会生成can.obj,因为can.obj中有vars.obj所有的东西。所以链接器将各个.obj文件链接成.exe时就会出现重定义的错误。解决方法是将将变量的定义改成声明就行,比如int a;改成extern int a;不过这时vars.cpp的作用相当于一个头文件了,变量的定义还得在另一个文件里定义才行。以前只知道.h文件中放的是声明,对应的.cpp文件是.h文件声明的实现,也不怎么理解。今天终于弄明白了这一点,乱来会出现这个错误。声明放在.h中,实现放在.cpp中,需要用到.h中变量和类或是成员函数时,只需要在需要用到这些东东的源文件中直接#include“xxx.h”就行,因为头文件中只有声明,没有定义。如果只有.h文件而没有头文件声明的实现(即对应的.cpp文件)的话,就会出现另一个错误了:error LNK2001无法解析的外部符号xxx,这时因为只有声明没有实现,在对应的.cpp文件中将头文件的变量实现就好了。变量和函数和类可以声明很多次但只能定义一次,包含进头文件,也就是包含的只是声明,多包含几次相当于多声明了几次没有问题的。现在can.obj与vars.obj中没有重复定义的量,can.cpp包含的是vars.h,vars.h是声明。若果要保证源文件只包含一次.h,例如,can.cpp中要保证只包含vars.h一次,就要 使用宏定义了:#ifndef _VARS_H  #define _VARS_H ......#endif,省略号代表的是原来vars.h中的所有东西,即只需在原来的vars.h开头加上#ifndef _VARS_H  #define _VARS_H ,结尾加上#endif。多次包含标准头文件是没问题的,例如vars.h中有#include,can.cpp中也有#include,可以打开看一看iostream的内容:#ifndef _IOSTREAM_   #define _IOSTREAM_。。。。。。#endif /* _IOSTREAM_ */。但自己的头文件需要自己定义好宏。如果不包含头文件,在需要用到某些变量的时候声明一下也可以,extern。。。,但如果用到的量比较多,那么包含进头文件将省事的多。

你可能感兴趣的:(c/c++)