当构建我的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

当前回答

这是GCC中的一个错误特性。也就是说,g++编译器本身不能抱怨未定义的虚方法,因为它们可以在其他地方定义。但是-它不存储关于缺少哪些虚拟成员的信息;它只存储了一个und定义的虚表符号,链接器会抱怨。

相反,如果要列出缺少的成员,则链接器可以告诉您它们是什么。

关于这个问题,GCC有一个公开的bug: bug 42540。不幸的是,它已经13岁了。

其他回答

对于Qt用户使用CMakeList.txt

在你的CMakeLists.txt中添加这一行:

正如Chris Morler所解释的,如果你忘记moc一个头部,你会得到这个错误

你确定CDasherComponent有一个析构函数体吗?它肯定不在这里——问题是它是否在.cc文件中。 从样式的角度来看,CDasherModule应该显式地定义它的析构函数虚函数。 看起来CGameModule在末尾有一个额外的}(在}之后;//类)。 CGameModule是否被链接到定义CDasherModule和CDasherComponent的库中?

不是过柱而是。如果你在处理继承问题,第二次谷歌命中是我错过的,即。应该定义所有虚方法。

如:

virtual void fooBar() = 0;

详细信息请参见answare c++对虚表和继承的未定义引用。刚刚意识到上面已经提到了,但它可能会帮助到一些人。

GNU c++编译器必须决定将虚表放在哪里,以防对象的虚函数定义分布在多个编译单元中(例如,一些对象的虚函数定义在一个.cpp文件中,另一些在另一个.cpp文件中,等等)。

编译器选择将虚函数表放在与第一个声明的虚函数定义相同的位置。

现在,如果由于某种原因忘记为对象中声明的第一个虚函数提供定义(或者错误地忘记在链接阶段添加已编译的对象),您将得到这个错误。

作为一个副作用,请注意,只有对于这个特定的虚函数,你才不会得到传统的链接错误,比如你缺少函数foo。

当我试图实现抽象工厂模式时,我也有这个问题,但忘记了链接一些库。因此,如果没有帮助喷射,检查是否所有必需的库都被链接