[c++] Undefined reference to vtable


Answers

For what it is worth, forgetting a body on a virtual destructor generates the following:

undefined reference to `vtable for CYourClass'.

I am adding a note because the error message is deceptive. (This was with gcc version 4.6.3.)

Question

So, I'm getting the infamously horrible "undefined reference to 'vtable..." error for the following code (The class in question is CGameModule.) and I cannot for the life of me understand what the problem is. At first, I thought it was related to forgetting to give a virtual function a body, but as far as I understand, everything is all here. The inheritance chain is a little long, but here is the related source code. I'm not sure what other information I should provide.

Note: The constructor is where this error is happening, it'd seem.

My code:

class CGameModule : public CDasherModule {
 public:
  CGameModule(Dasher::CEventHandler *pEventHandler, CSettingsStore *pSettingsStore, CDasherInterfaceBase *pInterface, ModuleID_t iID, const char *szName)
  : CDasherModule(pEventHandler, pSettingsStore, iID, 0, szName)
  { 
      g_pLogger->Log("Inside game module constructor");   
      m_pInterface = pInterface; 
  }

  virtual ~CGameModule() {};

  std::string GetTypedTarget();

  std::string GetUntypedTarget();

  bool DecorateView(CDasherView *pView) {
      //g_pLogger->Log("Decorating the view");
      return false;
  }

  void SetDasherModel(CDasherModel *pModel) { m_pModel = pModel; }


  virtual void HandleEvent(Dasher::CEvent *pEvent); 

 private:



  CDasherNode *pLastTypedNode;


  CDasherNode *pNextTargetNode;


  std::string m_sTargetString;


  size_t m_stCurrentStringPos;


  CDasherModel *m_pModel;


  CDasherInterfaceBase *m_pInterface;
};

Inherits from...

class CDasherModule;
typedef std::vector<CDasherModule*>::size_type ModuleID_t;

/// \ingroup Core
/// @{
class CDasherModule : public Dasher::CDasherComponent {
 public:
  CDasherModule(Dasher::CEventHandler * pEventHandler, CSettingsStore * pSettingsStore, ModuleID_t iID, int iType, const char *szName);

  virtual ModuleID_t GetID();
  virtual void SetID(ModuleID_t);
  virtual int GetType();
  virtual const char *GetName();

  virtual bool GetSettings(SModuleSettings **pSettings, int *iCount) {
    return false;
  };

 private:
  ModuleID_t m_iID;
  int m_iType;
  const char *m_szName;
};

Which inherits from....

namespace Dasher {
  class CEvent;
  class CEventHandler;
  class CDasherComponent;
};

/// \ingroup Core
/// @{
class Dasher::CDasherComponent {
 public:
  CDasherComponent(Dasher::CEventHandler* pEventHandler, CSettingsStore* pSettingsStore);
  virtual ~CDasherComponent();

  void InsertEvent(Dasher::CEvent * pEvent);
  virtual void HandleEvent(Dasher::CEvent * pEvent) {};

  bool GetBoolParameter(int iParameter) const;
  void SetBoolParameter(int iParameter, bool bValue) const;

  long GetLongParameter(int iParameter) const;
  void SetLongParameter(int iParameter, long lValue) const;

  std::string GetStringParameter(int iParameter) const;
  void        SetStringParameter(int iParameter, const std::string & sValue) const;

  ParameterType   GetParameterType(int iParameter) const;
  std::string     GetParameterName(int iParameter) const;

 protected:
  Dasher::CEventHandler *m_pEventHandler;
  CSettingsStore *m_pSettingsStore;
};
/// @}


#endif



If you are using Qt, try rerunning qmake. If this error is in the widget's class, qmake might have failed to notice that the ui class vtable should be regenerated. This fixed the issue for me.




It's also possible that you get a message like

SomeClassToTest.host.o: In function `class1::class1(std::string const&)':
class1.hpp:114: undefined reference to `vtable for class1'
SomeClassToTest.host.o: In function `class1::~class1()':
class1.hpp:119: undefined reference to `vtable for class1'
collect2: error: ld returned 1 exit status
[link] FAILED: 'g++' '-o' 'stage/tests/SomeClassToTest' 'object/tests/SomeClassToTest.host.o' 'object/tests/FakeClass1.SomeClassToTest.host.o'

if you forget to define a virtual function of a class FakeClass1 when you're trying to link a unit test for another class SomeClass.

//class declaration in class1.h
class class1
{
    public:
    class1()
    {
    }
    virtual ~class1()
    {
    }
    virtual void ForgottenFunc();
};

And

//class definition in FakeClass1.h
//...
//void ForgottenFunc() {} is missing here

In this case I suggest you check out your fake for class1 once again. You'll probably find that you may have forgotten to define a virtual function ForgottenFunc in your fake class.




I got this error just because the name of a constructor argument differed in the header file and in the implementation file. The constructor signature is

PointSet (const PointSet & pset, Parent * parent = 0);

and what I wrote in the implementation started with

PointSet (const PointSet & pest, Parent * parent)

thus I accidentaly replaced "pset" with "pest". The compiler was complaining about this one and two other constructors in which there was no error at all. I'm using g++ version 4.9.1 under Ubuntu. And defining a virtual destructor in this derived class made no difference (it is defined in the base class). I would have never found this bug if I didn't paste the constructors' bodies in the header file, thus defining them in-class.




If all else fails, look for duplication. I was misdirected by the explicit initial reference to constructors and destructors until I read a reference in another post. It's any unresolved method. In my case, I thought I had replaced the declaration that used char *xml as the parameter with one using the unnecessarily troublesome const char *xml, but instead, I had created a new one and left the other one in place.




Not perhaps. Definitely ~CDasherModule() {} is missing.




Ok, the solution to this is that you may have missed out on the definition. See the example below to avoid the vtable compiler error:

// In the CGameModule.h

class CGameModule
{
public:
    CGameModule();
    ~CGameModule();

    virtual void init();
};

// In the CGameModule.cpp

#include "CGameModule.h"

CGameModule::CGameModule()
{

}

CGameModule::~CGameModule()
{

}

void CGameModule::init()    // Add the definition
{

}



Perhaps missing the virtual destructor is contributing factor?

virtual ~CDasherModule(){};



Not to cross post but. If you are dealing with inheritance the second google hit was what I had missed, ie. all virtual methods should be defined.

Such as:

virtual void fooBar() = 0;

See answare C++ Undefined Reference to vtable and inheritance for details. Just realized it's already mentioned above, but heck it might help someone.




I simply got this error because my cpp file was not in the makefile.




The GNU C++ compiler has to make a decision where to put the vtable in case you have the definition of the virtual functions of an object spread across multiple compilations units (e.g. some of the objects virtual functions definitions are in a .cpp file others in another .cpp file, and so on).

The compiler chooses to put the vtable in the same place as where the first declared virtual function is defined.

Now if you for some reason forgot to provide a definition for that first virtual function declared in the object (or mistakenly forgot to add the compiled object at linking phase), you will get this error.

As a side effect, please note that only for this particular virtual function you won't get the traditional linker error like you are missing function foo.




So I was using Qt with Windows XP and MinGW compiler and this thing was driving me crazy.

Basically the moc_xxx.cpp was generated empty even when I was added

Q_OBJECT

Deleting everything making functions virtual, explicit and whatever you guess doesn't worked. Finally I started removing line by line and it turned out that I had

#ifdef something

Around the file. Even when the #ifdef was true moc file was not generated.

So removing all #ifdefs fixed the problem.

This thing was not happening with Windows and VS 2013.




I got this type of error in situations where I was trying to link to an object when I got a make bug that prevented the object being added to the archive.

Say I have libXYZ.a that supposed to have bioseq.o in int but it does not.

I got an error:

combineseq.cpp:(.text+0xabc): undefined reference to `vtable for bioseq'

This is quit different from all of the above. I would call this missing object in the archive problem.




Related



Tags

c++ c++   gcc   g++