這裏我有三個源文件:Base.hpp, Base.cpp 和 main.cppios
在Base.hpp裏面定義一個基類,注意,基類只包含構造函數和析構函數的聲明,函數在Base.cpp裏實現。函數
此外在Base.hpp中還有一個函數的定義(函數聲明和定義都在Base.hpp文件中)三個文件代碼以下。this
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; }
定義類時,通常聲明和實現分離,因而可將頭文件中定義的類的構造函數,移到其對應的xxxx.cpp中,你會發現果真問題解決了。
實際上,xxxx.cpp因爲包含了xxxx.h,而xxxx.h中包含了構造函數的實現,因而xxxx.cpp生成目標文件的時候,包含了構造函數的實現。而類的調用函數,如main.cpp也包含了xxxx.h,一樣編譯生成目標文件的時候,也會包含構造函數的實現。這樣兩者在連接階段就會發現有兩個如出一轍的函數,出現了重定義的問題。spa
肯定了這是因爲兩個實現文件(main.cpp 和 base.cpp)中重複包含了頭文件而形成的。
要注意的是,在這裏,在頭文件中加入#ifndef……#endif這樣的預編譯命令是沒用的,由於這是防止嵌套包含頭文件的,而本例中並無嵌套包含,是 在兩個文件中分別包含。.net
方法1:
只在頭文件中聲明函數,把函數定義都放到cpp文件中,本例中把platform函數的定義從Base.hpp文件中移到Base.cpp文件中。code
把函數體放到cpp文件中後確實可行。orm
同理:若是在頭文件中再定義一個變量:int a = 10; 那麼因爲頭文件在兩個cpp文件中都有被包含,也會出現相似的錯誤。blog
此時,須要把變量的定義放到Base.cpp文件中。get
方法2:string
在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