Απροσδιόριστη αναφορά σε vtable

Κατά την κατασκευή του προγράμματος C++, λαμβάνω το μήνυμα σφάλματος

undefined reference to '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;
};

Inherits from...

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 έχει ένα λήμμα σχετικά με αυτό:

Η λύση είναι να εξασφαλιστεί ότι όλες οι εικονικές μέθοδοι που δεν είναι καθαρές ορίζονται. Σημειώστε ότι ένας καταστροφέας πρέπει να οριστεί ακόμα και αν έχει δηλωθεί καθαρά εικονικός [class.dtor]/7.

Σχόλια (9)
Λύση

Έτσι, κατάλαβα το πρόβλημα και ήταν ένας συνδυασμός κακής λογικής και μη εξοικείωσης με τον κόσμο του automake/autotools. Προσέθετα τα σωστά αρχεία στο πρότυπο Makefile.am, αλλά δεν ήμουν σίγουρος ποιο βήμα στη διαδικασία κατασκευής μας δημιούργησε πραγματικά το ίδιο το makefile. Έτσι, έκανα μεταγλώττιση με ένα παλιό makefile που δεν είχε καμία ιδέα για τα νέα μου αρχεία.

Ευχαριστώ για τις απαντήσεις και τον σύνδεσμο στις συχνές ερωτήσεις του GCC. Θα φροντίσω να το διαβάσω αυτό για να αποφύγω την εμφάνιση αυτού του προβλήματος για πραγματικό λόγο.

Σχόλια (7)
  • Είστε σίγουροι ότι το CDasherComponent έχει ένα σώμα για τον καταστροφέα; Σίγουρα δεν είναι εδώ - το ερώτημα είναι αν υπάρχει στο αρχείο .cc.
  • Από την άποψη του στυλ, το CDasherModule θα πρέπει να ορίζει ρητά τον καταστροφέα του virtual.
  • Φαίνεται ότι το CGameModule έχει ένα επιπλέον } στο τέλος (μετά το }; // για την κλάση).
  • Συνδέεται το CGameModule με τις βιβλιοθήκες που ορίζουν τις CDasherModule και CDasherComponent;
Σχόλια (2)