我在头文件中有所有类定义:ModelModule.h。我已经在下面提供了该文件的示例代码,其中我已经给出了2个类及其成员函数的声明:
#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)
{
}
我摆脱了任何语法错误的代码。但是,当我构建代码时,我得到错误make: * [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 ****
我查看了这个论坛的vtable错误,并且提到问题是当我们声明构造函数/析构函数但从未定义它时。但在这种情况下,这似乎不是一个问题,因为它是在ModelModule.cpp中明确完成的。这里似乎有一些非常基本的东西正在引起我的注意。
答案 0 :(得分: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':
vtable for MyClass
prog.cpp:(.text+0x19): undefined reference to.
MyClass :: doSomethingMore()'
prog.cpp:(.text+0x1e): undefined reference to
collect2:ld返回1退出状态
如您所见,GCC因报告此类特定问题的错误而臭名昭着。
它是否以某种方式与构造函数和析构函数链接?
gcc faq 也会对其进行处理:
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]
在类中声明的虚函数应在该类中定义或声明为纯(10.4),或两者兼有;但不需要诊断(3.2)。