error LNK2005: “找到一个或多个多重定义的符号” 已经在 xxxx.obj 中定义 的解决方法
1 问题还原
这里我有三个源文件:Base.hpp, Base.cpp 和 main.cpp
在Base.hpp里面定义一个基类,注意,基类只包含构造函数和析构函数的声明,函数在Base.cpp里实现。
此外在Base.hpp中还有一个函数的定义(函数声明和定义都在Base.hpp文件中)三个文件代码如下。
Base.hpp
#ifndef VIRTUAL_H #define VIRTUAL_H #include<iostream> #include<string> using namespace std; class Base{ public: Base(); ~Base(); private: char *p; }; void platform(Base *pBase){ cout << "this is just a function..." << endl; } #endif
Base.cpp
#include"Base.hpp" Base::Base(){ cout << "construction function..." << endl; } Base::~Base(){ cout << "destructor function..." << endl; delete p; }
main.cpp
#include"Base.hpp" #include<iostream> using namespace std; int main(){ cout << "main..." << endl; Base * pBase = new Base; delete pBase; system("pause"); return 0; }
2 分析与解决方案
2.1 分析
定义类时,一般声明和实现分离,于是可将头文件中定义的类的构造函数,移到其对应的xxxx.cpp中,你会发现果然问题解决了。
实际上,xxxx.cpp由于包含了xxxx.h,而xxxx.h中包含了构造函数的实现,于是xxxx.cpp生成目标文件的时候,包含了构造函数的实现。而类的调用函数,如main.cpp也包含了xxxx.h,同样编译生成目标文件的时候,也会包含构造函数的实现。这样二者在链接阶段就会发现有两个一模一样的函数,出现了重定义的问题。
确定了这是由于两个实现文件(main.cpp 和 base.cpp)中重复包含了头文件而造成的。
要注意的是,在这里,在头文件中加入#ifndef……#endif这样的预编译命令是没用的,因为这是防止嵌套包含头文件的,而本例中并没有嵌套包含,是 在两个文件中分别包含。
2.2 解决
方法1:
只在头文件中声明函数,把函数定义都放到cpp文件中,本例中把platform函数的定义从Base.hpp文件中移到Base.cpp文件中。
把函数体放到cpp文件中后确实可行。
同理:如果在头文件中再定义一个变量:int a = 10; 那么由于头文件在两个cpp文件中都有被包含,也会出现类似的错误。
此时,需要把变量的定义放到Base.cpp文件中。
方法2:
在xxxx.h的类的函数定义处,加上inline。这样实际上是在调用处展开函数体代码,代替函数调用。从而避免重复定义的问题。
头文件
class xxxxx { public: inline xxxxx(const Eigen::VectorXd &xData, const Eigen::VectorXd &yData); private: Eigen::VectorXd m_xData; Eigen::VectorXd m_yData; }; xxxxx::xxxxx( const Eigen::VectorXd &xData, const Eigen::VectorXd &yData) { m_xData = xData; m_yData = yData; }
参考文章
fatal error LNK1169: 找到一个或多个多重定义的符号 的解决方案,xiamentingtao,2017-1
没有整理与归纳的知识,一文不值!高度概括与梳理的知识,才是自己真正的知识与技能。 永远不要让自己的自由、好奇、充满创造力的想法被现实的框架所束缚,让创造力自由成长吧! 多花时间,关心他(她)人,正如别人所关心你的。理想的腾飞与实现,没有别人的支持与帮助,是万万不能的。