Riferimento indefinito a vtable

Quando costruisco il mio programma C++, ricevo il messaggio di errore

riferimento non definito a 'vtable...

Qual è la causa di questo problema? Come posso risolverlo?


Si dà il caso che sto ricevendo l'errore per il seguente codice (La classe in questione è CGameModule.) e non riesco a capire quale sia il problema. All'inizio pensavo fosse legato alla dimenticanza di dare un corpo ad una funzione virtuale, ma per quanto ho capito, è tutto qui. La catena di ereditarietà è un po' lunga, ma ecco il codice sorgente relativo. Non sono sicuro di quali altre informazioni dovrei fornire.

Nota: Il costruttore è dove questo errore sta accadendo, sembrerebbe.

Il mio codice:

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

Eredita da...

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

Che eredita da....

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

La GCC FAQ ha una voce al riguardo:

La soluzione è assicurarsi che tutti i metodi virtuali che non sono puri siano definiti. Notate che un distruttore deve essere definito anche se è dichiarato puro-virtuale [class.dtor]/7.

Commentari (9)
Soluzione

Quindi, ho capito il problema ed è stata una combinazione di cattiva logica e di non essere totalmente familiare con il mondo di automake/autotools. Stavo aggiungendo i file corretti al mio modello Makefile.am, ma non ero sicuro di quale passo del nostro processo di compilazione creasse effettivamente il makefile stesso. Quindi, stavo compilando con un vecchio makefile che non aveva idea dei miei nuovi file.

Grazie per le risposte e il link alle FAQ di GCC. Mi assicurerò di leggerlo per evitare che questo problema si verifichi per una vera ragione.

Commentari (7)
  • Sei sicuro che CDasherComponent abbia un corpo per il distruttore? Sicuramente non è qui - la domanda è se è nel file .cc.
  • Dal punto di vista dello stile, CDasherModule dovrebbe definire esplicitamente il suo distruttore virtuale.
  • Sembra che CGameModule abbia un } extra alla fine (dopo il }; // per la classe).
  • È CGameModule ad essere collegato alle librerie che definiscono CDasherModule e CDasherComponent?
Commentari (2)