Eclipse C++ project not building: Constructor Destructor Issue

Go To StackoverFlow.com

2

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.

  • What is it that I'm missing?
  • Can you tell me what is with the virtual function and how it caused the error to come?
  • Does it somehow link up with the constructor and destructor?
2012-04-04 07:29
by sriramn
Have you provided definitions for All the methods which you declared as virtual? The error is typical where you miss providing defintion for a virtual method.Standard mandates all the methods except pure virtual should have a definition - Alok Save 2012-04-04 07:31
virtual void Configure(void){}; virtual void loadXmlString(xmlNodePtr pXmlNode, xmlDocPtr pXmlDoc, xmlChar * con); virtual void SaveXml(std::ofstream& fout){}; - I have defined these three... - sriramn 2012-04-04 07:37
How about CModelModule::loadXmlString - Some programmer dude 2012-04-04 07:56
You need to add empty function definition for loadXmlString as you have done for SaveXml (virtual void loadXmlString(xmlNodePtr pXmlNode, xmlDocPtr pXmlDoc, xmlChar * con){}) or make it a pure virtual function (virtual void loadXmlString(xmlNodePtr pXmlNode, xmlDocPtr pXmlDoc, xmlChar * con) = 0;). Also semi-colon after function definition of SaveXml & Configure are redundan - another.anon.coward 2012-04-04 08:05
@another.anon.coward - That was it!! I had not defined the virtual version of the loadXmlString().... The code got built!! Thanks a lot to all you guys!!

For knowledge and self education: Can you tell me what is with the virtual function and how it caused the error to come? Does it somehow link up with the constructor and destructor - sriramn 2012-04-04 08:20

@RazorXsr: I added an explanation about the problem.Hth - Alok Save 2012-04-04 08:42
You also need to make ~CModelModule virtual, since inheritance of polymorphic class requires it's destructor to be virtual - abyss.7 2012-04-04 11:07


3

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':
prog.cpp:(.text+0x19): undefined reference to
vtable for MyClass.
prog.cpp:(.text+0x1e): undefined reference to
MyClass::doSomethingMore()'
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).

2012-04-04 08:31
by Alok Save
That made the problem crystal and put it in proper perspective!! Thank you - sriramn 2012-04-04 15:18
Ads