2012-04-04 121 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