I have all the class definitions in a header file: ModelModule.h. I have provided the sample code for that file below where I have given the declaration of 2 classes and its member functions:
#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);
};
Now the function definitions has been given in a .cpp file: ModelModule.cpp. Note: The header file has been included
#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)
{
}
I have rid the code of any syntactic error. However when I build the code I get the error make: *[ProjectName] Error1. On inspecting the console I find the following being displayed:
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 ****
I checked out this forum for the vtable error and it was mentioned that the problem is when we declare a constructor/destructor but never define it. But that does not seem to be a problem in this case as it was explicitly done in ModelModule.cpp. There seems to be something very basic that is going on here that is slipping my attention.
Root Cause:
You get the error because the C++ Standard mandates that All virtual methods of a class except the pure virtual methods Must have a definition[#1].
Solution:
Either provide definitions to all your virtual
methods or make them pure virtual
.
Explanation:
The error generated by gcc in such scenarios is at best mis-leading. Here is a sample program which demonstrates the problem you have:
class MyClass
{
public:
virtual void doSomething() { }
virtual void doSomethingMore();
};
int main()
{
MyClass obj;
obj.doSomething();
obj.doSomethingMore();
return 0;
}
compilation info:
/home/4VqWl0/ccMjLi2V.o: In function
main':
vtable for MyClass
prog.cpp:(.text+0x19): undefined reference to.
MyClass::doSomethingMore()'
prog.cpp:(.text+0x1e): undefined reference to
collect2: ld returned 1 exit status
As you see GCC is notorious in reporting errors for this particular type of problem.
Does it somehow link up with the constructor and destructor?
The gcc faq doccuments it as well:
The ISO C++ Standard specifies that all virtual methods of a class that are not pure-virtual must be defined, but does not require any diagnostic for violations of this rule
[class.virtual]/8
. Based on this assumption, GCC will only emit the implicitly defined constructors, the assignment operator, the destructor and the virtual table of a class in the translation unit that defines its first such non-inline method.Therefore, if you fail to define this particular method, the linker may complain about the lack of definitions for apparently unrelated symbols. Unfortunately, in order to improve this error message, it might be necessary to change the linker, and this can't always be done.
The solution is to ensure that all virtual methods that are not pure are defined. Note that a destructor must be defined even if it is declared pure-virtual
[class.dtor]/7
.
Good Read:
What does it mean that the "virtual table" is an unresolved external?
[#1]C++03 Standard: 10.3 Virtual functions [class.virtual]
A virtual function declared in a class shall be defined, or declared pure (10.4) in that class, or both; but no diagnostic is required (3.2).