Referencia indefinida a vtable

Cuando construyo mi programa en C++, recibo el mensaje de error

referencia indefinida a 'vtable...

¿Cuál es la causa de este problema? ¿Cómo puedo solucionarlo?


Resulta que me sale el error del siguiente código (La clase en cuestión es CGameModule.) y no consigo entender cuál es el problema. Al principio, pensé que estaba relacionado con el olvido de dar un cuerpo a una función virtual, pero por lo que entiendo, todo está aquí. La cadena de herencia es un poco larga, pero aquí está el código fuente relacionado. No estoy seguro de qué otra información debo proporcionar.

Nota: El constructor es donde este error está sucediendo, it'd parece.

Mi código:

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

Hereda de...

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

Que hereda de....

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

El GCC FAQ tiene una entrada sobre ello:

La solución es asegurarse de que todos los métodos virtuales que no son puros están definidos. Tenga en cuenta que un destructor debe ser definido incluso si se declara puro-virtual [class.dtor]/7.

Comentarios (9)
Solución

Así que, he descubierto el problema y fue una combinación de mala lógica y no estar totalmente familiarizado con el mundo automake/autotools. Estaba añadiendo los archivos correctos a mi plantilla Makefile.am, pero no estaba seguro de qué paso de nuestro proceso de construcción creaba realmente el propio makefile. Así que estaba compilando con un viejo makefile que no tenía ni idea de mis nuevos archivos.

Gracias por las respuestas y por el enlace al GCC FAQ. Me aseguraré de leerlo para evitar que este problema ocurra por una razón real.

Comentarios (7)
  • ¿Estás seguro de que CDasherComponent tiene un cuerpo para el destructor? Definitivamente no está aquí - la pregunta es si está en el archivo .cc.
  • Desde una perspectiva de estilo, CDasherModule debería definir explícitamente su destructor virtual.
  • Parece que CGameModule tiene un } extra al final (después del }; // para la clase).
  • ¿Está CGameModule enlazado con las bibliotecas que definen CDasherModule y CDasherComponent?
Comentarios (2)