vtableへの未定義の参照

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 FAQ]1には、それに関する項目があります。

解決策は、純粋ではないすべての仮想メソッドが定義されていることを確認することです。なお、デストラクタは純仮想宣言されていても定義しなければなりません [class.dtor]/7。

解説 (9)
ソリューション

問題を解決したのですが、それは論理的に間違っていたことと、automake/autotoolsの世界に全く精通していなかったことの組み合わせでした。正しいファイルをMakefile.amテンプレートに追加していたのですが、ビルドプロセスのどのステップで実際にmakefile自体を作成するのかがわからなかったのです。そのため、新しいファイルのことを全く知らない古い makefile を使ってコンパイルしていました。

回答とGCC FAQへのリンクをありがとうございました。この問題が本当の理由で発生しないように、必ず読むようにします。

解説 (7)
  • CDasherComponent`にデストラクタ用のボディがあるのは確かでしょうか? 問題は、.ccファイルにあるかどうかです。
  • スタイルの観点からすると、CDasherModule はデストラクタを明示的に virtual と定義すべきです。
  • CGameModuleには最後に余分な}があるように見えます (クラスの}; // の後)。
  • CGameModuleCDasherModuleCDasherComponent` を定義しているライブラリとリンクされていますか?
解説 (2)