Неопределенная ссылка на vtable - PullRequest
286 голосов
/ 17 июня 2010

При сборке моей программы на C ++ я получаю сообщение об ошибке

неопределенная ссылка на 'vtable ...

В чем причина этой проблемы? Как мне это исправить?


Так получилось, что я получаю сообщение об ошибке для следующего кода (рассматриваемый класс - CGameModule.), И я не могу понять, в чем проблема. Сначала я думал, что это связано с забвением придания виртуальной функции тела, но, насколько я понимаю, все здесь. Цепочка наследования немного длинна, но вот соответствующий исходный код. Я не уверен, какую еще информацию я должен предоставить.

Примечание: конструктор, где эта ошибка происходит, казалось бы.

Мой код:

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;
};

Наследуется от ...

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;
};

Который наследует от ....

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

Ответы [ 27 ]

7 голосов
/ 18 августа 2014

Не пересекать пост, но. Если вы имеете дело с наследованием , то вторым попаданием в Google было то, что я пропустил, т.е. все виртуальные методы должны быть определены.

Например:

virtual void fooBar() = 0;

Подробнее см. Answare C ++ Undefined Ссылка на vtable и наследование . Просто понял, что это уже упоминалось выше, но, черт возьми, это может кому-то помочь.

7 голосов
/ 23 января 2017

Хорошо, решение этого в том, что вы, возможно, пропустили определение.Смотрите пример ниже, чтобы избежать ошибки компилятора vtable:

// 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
{

}
6 голосов
/ 18 июня 2010
  • Вы уверены, что CDasherComponent имеет тело для деструктора?Это определенно не здесь - вопрос в том, находится ли он в файле .cc.
  • С точки зрения стиля, CDasherModule должен явно определять его деструктор virtual.
  • Это похоже на CGameModule имеет дополнительный } в конце (после }; // for the class).
  • Связан ли CGameModule с библиотеками, которые определяют CDasherModule и CDasherComponent?
5 голосов
/ 05 января 2017

Это был первый результат поиска для меня, поэтому я решил добавить еще одну вещь для проверки: убедиться, что определение виртуальных функций действительно в классе.В моем случае у меня было это:

Заголовочный файл:

class A {
 public:
  virtual void foo() = 0;
};

class B : public A {
 public:
  void foo() override;
};

и в моем .cc файле:

void foo() {
  ...
}

Это должно читаться

void B::foo() {
}
5 голосов
/ 17 сентября 2014

Возможно, отсутствующий виртуальный деструктор является фактором?

virtual ~CDasherModule(){};
3 голосов
/ 18 декабря 2016

Так что я использовал Qt с Windows XP и компилятором MinGW, и это сводило меня с ума.

Обычно moc_xxx.cpp генерировался пустым, даже когда я был добавлен

Q_OBJECT

Удаление всего, что делает функции виртуальными, явными и все, что вы думаете, не работает. Наконец я начал удалять построчно, и оказалось, что у меня есть

#ifdef something

Вокруг файла. Даже когда #ifdef был истинным, файл moc не был сгенерирован.

Таким образом, удаление всех #ifdefs решило проблему.

Этого не происходило с Windows и VS 2013.

3 голосов
/ 10 ноября 2016

Здесь так много ответов, но, похоже, ни один из них не охватил мою проблему.У меня было следующее:


class I {
    virtual void Foo()=0;
};

И в другом файле (конечно, включен в компиляцию и компоновку)

class C : public I{
    void Foo() {
        //bar
    }
};

Ну, это не сработалои я получил ошибку, о которой все говорят.Чтобы решить эту проблему, мне пришлось убрать фактическое определение Foo из объявления класса следующим образом:

class C : public I{
    void Foo();
};

C::Foo(){
   //bar
}

Я не гуру C ++, поэтому не могу объяснить, почему это более правильно, но это решилопроблема для меня.

3 голосов
/ 04 ноября 2014

Не возможно.Определенно ~CDasherModule() {} отсутствует.

2 голосов
/ 30 июня 2017

В моем случае я использую Qt и определил подкласс QObject в файле foo.cpp (не .h). Исправление должно было добавить #include "foo.moc" в конце foo.cpp.

2 голосов
/ 15 августа 2014

Если ничего не помогает, поищите дубликаты.Я был сбит с толку явной исходной ссылкой на конструкторы и деструкторы, пока не прочитал ссылку в другом посте.Это любой неразрешенный метод.В моем случае я подумал, что заменил объявление, в котором в качестве параметра использовался char * xml, на использование ненужного хлопотного const char * xml, но вместо этого я создал новое и оставил другое на месте.

...