2012-04-04 120 views
2

我在頭文件中包含所有類定義:ModelModule.h。我所提供的示例代碼下面,我已經給2類和其成員函數的聲明文件:Eclipse C++項目不構建:構造函數析構函數問題

#pragma once 

#if !defined(MODELMODULE_H) 
#define MODELMODULE_H 


//Required header files 

class CModelModule; 
class COrdProbitMM; 

class CModelModule 
// virtual base class for all types of modeling modules 
{ 
    friend class CSimCoordinator; 
    friend class CHouseholdCoordinator; 
    friend class CGenericHousehold; 

    public: 
     CModelModule(void); 
     ~CModelModule(void); 

    protected: 
     std::string   m_Label;   
     std::vector<int>  m_AvailEndAttr;  
     void GetVarValues(std::vector<int>&, std::vector<double> &); 


    public: 


     virtual void Configure(void){}; 
     virtual void loadXmlString(xmlNodePtr pXmlNode, xmlDocPtr pXmlDoc, xmlChar * con); 
     virtual void SaveXml(std::ofstream& fout){}; 

     double mrand(void); 
     double UniformRand();   // returns a U[0,1] random number 
     double StdNormalRand();  // returns a N(0,1) random number 
}; 

class COrdProbitMM : public CModelModule 
// Class represent the ordered-probit models 
{ 
    friend class CSimCoordinator; 
    friend class CHouseholdCoordinator; 
    friend class CMMRunner; 

    public: 
     COrdProbitMM(CSimCoordinator& simcord, std::string& sLabel); 
     COrdProbitMM(CSimCoordinator& simcord, std::string& sLabel, int nAlts); 
     ~COrdProbitMM(void); 

    private: 

     int    m_Max_nAlts;  
     std::vector<double>  m_Thresholds; 

    public: 
     void Configure(void); 
     void copyConfigure(COrdProbitMM* that); 

     int Run(CHouseholdObject*); 
     int Run(CPersonObject*); 


     void loadXmlString(xmlNodePtr pConfNode, xmlDocPtr pXmlDoc, xmlChar* con); 

    private: 
     int  Run(void); 
}; 

現在函數定義已在cpp文件被給出:ModelModule.cpp。注:頭文件已包含在內

#include "ModelModule.h" 
//Other header files 

//Code for all the other functions defined here 

//Given below are the code for how the constructors and destructors are defined 

COrdProbitMM::~COrdProbitMM(void) 
{ 
} 

CModelModule::CModelModule(void) 
{ 
} 

CModelModule::~CModelModule(void) 
{ 
} 

我擺脫了任何語法錯誤的代碼。但是,當我構建代碼時,出現錯誤代碼:* [ProjectName] Error1。在檢查控制檯我發現顯示以下福利:

Building target: Project Name 
Invoking: GCC C++ Linker 
g++ -o "XYZ" ./src/XYZ.o ./src/DataCache\ -\ Copy.o ./src/DataCache.o ./src/DataCoordinator.o ./src/DataObject.o ./src/HouseholdCoordinator.o ./src/ 
LinearEquation.o ./src/MMRunner.o ./src/MainFrm.o ./src/ModelModule.o ./src/SimCoordinator.o ./src/main.o -lxml2 -lsqlite3 

./src/ModelModule.o: In function `CModelModule::CModelModule()': 
ModelModule.cpp:(.text._ZN12CModelModuleC2Ev[CModelModule::CModelModule()]+0xd): undefined reference to `vtable for CModelModule' 
./src/ModelModule.o: In function `CModelModule::~CModelModule()': 
ModelModule.cpp:(.text._ZN12CModelModuleD2Ev[CModelModule::~CModelModule()]+0xd): undefined reference to `vtable for CModelModule' 

./src/ModelModule.o:(.rodata._ZTI12COrdProbitMM[typeinfo for COrdProbitMM]+0x8): undefined reference to `typeinfo for CModelModule' 

collect2: ld returned 1 exit status 
make: *** [Project Name] Error 1 

**** Build Finished **** 

我檢查了這個論壇的虛函數表的錯誤和它被提及的問題是,當我們宣佈一個構造函數/析構函數,但從來沒有定義它。但在這種情況下,這看起來並不成問題,因爲它在ModelModule.cpp中明確完成。似乎有一件非常基本的事情正在引起我的注意。

  • 我錯過了什麼?
  • 你能告訴我虛擬功能是什麼以及它如何導致錯誤發生?
  • 它以某種方式與構造函數和析構函數鏈接?
+1

您是否爲** All **提供了您聲明爲「虛擬」的方法的定義?如果你錯過了爲虛擬方法提供定義的錯誤,那麼典型的錯誤是標準。除了純虛擬方法之外,所有的方法都應該有一個定義。 – 2012-04-04 07:31:55

+0

virtual void Configure(void){}; virtual void loadXmlString(xmlNodePtr pXmlNode,xmlDocPtr pXmlDoc,xmlChar * con); virtual void SaveXml(std :: ofstream&fout){}; - 我已經定義了這三個.... – sriramn 2012-04-04 07:37:41

+0

'CModelModule :: loadXmlString'如何? – 2012-04-04 07:56:46

回答

3

根本原因:
你得到的錯誤,因爲C++標準授權所有虛擬除純虛方法必備一個類的方法有一個定義[#1]

解決方案:
要麼提供的定義,以你的所有virtual方法或使它們純粹virtual

說明:
在這樣的場景中與gcc產生的誤差是在最好的誤領先。這裏是一個sample program這表明你有問題:

class MyClass 
{ 
    public: 
    virtual void doSomething() { } 
    virtual void doSomethingMore(); 
}; 

int main() 
{ 
    MyClass obj; 
    obj.doSomething(); 
    obj.doSomethingMore(); 
    return 0; 
} 

編譯信息:

/home/4VqWl0/ccMjLi2V.o:在功能main':
prog.cpp:(.text+0x19): undefined reference to
虛函數表的MyClass的MyClass的.
prog.cpp:(.text+0x1e): undefined reference to
:: doSomethingMore()」
collect2:LD返回1個退出狀態

正如你看到GCC在這個特定類型的問題報告錯誤臭名昭著。

它以某種方式與構造函數和析構函數鏈接?

gcc faq doccuments它,以及:

的ISO C++標準指定不在純虛擬必須被定義,但類的所有虛擬方法不需要任何診斷侵犯這條規則[class.virtual]/8。基於這個假設,GCC將只在定義其第一個這種非內聯方法的轉換單元中發出隱式定義的構造函數,賦值運算符,析構函數和類的虛擬表。

因此,如果您未能定義此特定方法,則鏈接器可能會抱怨缺乏對無關標記的定義。不幸的是,爲了改善這個錯誤信息,可能有必要改變鏈接器,而這並不總是可以完成的。

解決方案是確保所有不純的虛擬方法都已定義。請注意,即使聲明爲純虛擬[class.dtor]/7,也必須定義析構函數。

讀取良好:

What does it mean that the "virtual table" is an unresolved external?


[#1]C++ 03標準:10.3虛函數[class.virtual]

虛函數dec在一個班級中應該被定義,或者被宣佈爲純粹的(10.4),或者兩者兼有;但不需要診斷(3.2)。

+1

這使問題水晶,並把它放在適當的角度!謝謝! – sriramn 2012-04-04 15:18:34