Undefined reference to vtable
Lors de la construction de mon programme en C++, j'obtiens le message d'erreur
undefined reference to 'vtable...
Quelle est la cause de ce problème? Comment puis-je résoudre ce problème?
Il se trouve que j'obtiens le message d'erreur pour le code suivant (La classe en question est CGameModule.) et je ne peux pas pour la vie de me comprendre quel est le problème. Au début, je pensais que c'était lié à l'oubli de donner une fonction virtuelle d'un corps, mais comme je le comprends, tout est ici. L'héritage de la chaîne est un peu long, mais ici, c'est le code source. Je ne suis pas sûr de ce que d'autres informations que je devrais fournir.
Remarque: Le constructeur est où cette erreur se produit, il avait l'air.
Mon code:
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;
};
Hérite 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;
};
Qui hérite de l'....
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
- Dont la fonction est de lancer le "undefined reference to vtable..." ?
- J'ai totalement raté que le message d'erreur indique une fonction. Il arrive à être le constructeur, donc j'ai vu mon nom de la classe et de ne pas faire le lien. Ainsi, le constructeur est en train de jeter ce. Je vais ajouter que le détail de mon post original.
Vous devez vous connecter pour publier un commentaire.
La GCC FAQ a une entrée sur elle:
nm -C CGameModule.o | grep CGameModule::
liste les méthodes qui sont définies, en supposant que l'ensemble de votre implémentation de la classe va dans la logique de l'objet fichier. Vous pouvez comparer cela avec ce qui est défini comme virtuel de comprendre ce que vous avez manqué.undefined reference to vtable for B D.o: undefined reference to typeinfo for B D.o: In function B::B() D.cpp: undefined reference to vtable for B
De la compilation D.cpp il fixe. Diff entre l'ancien et le nouveau D. o est: VIEUXU typeinfo for B U vtable for B
Nouveau00000000 V typeinfo for B 00000000 V typeinfo name for B 00000000 V vtable for B
qu'est-Ce que l'erreur de me dire exactement?Pour ce qu'il vaut, l'oubli d'un corps sur un destructeur virtuel génère les éléments suivants:
Je suis ajoutant une note car le message d'erreur est trompeur. (C'était avec la version de gcc 4.6.3.)
~Destructor = default;
dans le fichier d'en-tête n'a pas aidé. Est-il un bogue documenté déposée à l'encontre de gcc?Donc, j'ai compris le problème et c'était une combinaison de mauvaise logique, et n'étant pas familiarisé avec la automake/autotools monde. J'étais en ajoutant les fichiers corrects à mon Makefile.suis le modèle, mais je n'étais pas sûr de l'étape dans notre processus de fabrication a créé le makefile lui-même. Donc, j'ai eu de la compilation avec un vieux fichier "makefile" qui n'avait aucune idée à propos de mes nouveaux fichiers que ce soit.
Merci pour les réponses et le lien vers les pays du CCG FAQ. Je ne manquerai pas de lire que pour éviter que ce problème se produise pour une vraie raison.
Si vous êtes en utilisant Qt, essayez de relancer qmake. Si cette erreur est dans le widget de la classe, qmake peut-être pas de l'avis que l'interface de la classe vtable doit être régénéré. Cela a réglé le problème pour moi.
qmake
, j'ai eu le même aveccmake
. Partie fo le problème pourrait être que les deux outils ont un peu d'un problème avec les fichiers d'en-tête, qui pourrait ne pas toujours déclencher une reconstruction en cas de besoin.J'ai tout simplement eu cette erreur parce que mon fichier cpp n'était pas dans le makefile.
undefined reference to {function/class/struct}
quand il y a desvirtual
choses. M'a jeté.Undefined reference to vtable peut se produire en raison de la situation suivante aussi. Juste essayer ceci:
Classe A Contient:
Classe B Contient:
Classe C Contient: Maintenant, vous écrivez une Classe C dans lequel vous allez dériver de la Classe A.
Maintenant, si vous essayez de compiler, vous obtiendrez Undefined reference to vtable pour la Classe C comme une erreur.
Raison:
functionA
est défini comme virtuelle pure et sa définition est fournie dans la Classe B.functionB
est défini comme virtuel (PAS VIRTUELLE PURE) donc essaie d'en trouver la définition dans la Classe elle-même, mais vous avez fourni à sa définition dans la Classe B.Solution:
virtual void functionB(parameters) =0;
(Cela fonctionne il est Testé)
(J'espère que ça fonctionne comme je n'ai pas essayer)
Je viens de croiser une autre cause de cette erreur que vous pouvez vérifier.
La classe de base défini un fonction virtuelle pure comme:
Et de la sous-classe avait
Le problème était la faute de frappe que le
"=0"
était censé être en dehors de la parenthèse:Donc dans le cas où vous êtes défilement loin vers le bas, vous n'avez probablement pas trouver la réponse - c'est bien autre chose à vérifier.
Il y a beaucoup de spéculation, en effet, des réponses ici. Je vais ci-dessous donnent une code minimal qui reproduit cette erreur et d'expliquer pourquoi il se produit.
Assez Minime Code de Reproduire Cette Erreur
IBase.php
Dérivés.php
Derived.cpp
myclass.cpp
Vous pouvez le compiler avec GCC comme ceci:
Vous pouvez désormais reproduire l'erreur en supprimant
= 0
dans IBase.hpp. J'obtiens cette erreur:Explication
Avis que le code ci-dessus ne nécessite pas de virtuel, les destructeurs, les constructeurs ou tout autres fichiers supplémentaires pour les compiler pour réussir (bien que vous devriez les avoir).
La façon de comprendre cette erreur est comme suit:
L'éditeur de liens est à la recherche pour le constructeur de IBase. Ce qu'il va en avoir besoin pour le constructeur de la Dérivée. Cependant, comme Dérivé remplace les méthodes de IBase, il a vtable est attachée et qui fait référence à IBase. Lorsque l'éditeur de liens dit "undefined reference to vtable pour IBase" cela signifie essentiellement que le Dérivé a vtable référence à IBase, mais il ne trouve pas de code objet compilé de IBase à regarder vers le haut. De sorte que la ligne de fond est que la classe IBase a des déclarations sans implémentations. Cela signifie une méthode dans IBase est déclaré en tant que virtuel, mais nous avons oublié de le marquer comme virtuelle pure OU de fournir sa définition.
De Séparation À La Pointe
Si tout le reste échoue, alors l'un pour corriger cette erreur consiste à construire programme minimal qui ne compiler et ensuite les garder changer c'est donc à l'état que vous voulez. Entre les deux, garder la compilation pour voir quand il commence à échouer.
Note sur ROS et Chaton système de construction
Si vous avez été la compilation ci-dessus un ensemble de classes de ROS à l'aide de chaton système de construction, alors vous aurez besoin lignes suivantes dans CMakeLists.txt:
La première ligne dit essentiellement que nous voulons faire un exécutable nommé myclass et le code de construire ce qui peut être trouvé des fichiers qui suit. Un de ces fichiers doit avoir main(). Notez que vous n'avez pas à spécifier .php les fichiers de n'importe où dans CMakeLists.txt. Aussi, vous n'avez pas à spécifier Derived.cpp que d'une bibliothèque.
Ce qui peut arriver assez facilement si vous oubliez de lien vers le fichier objet qui a de la définition.
Le compilateur GNU C++ doit prendre une décision où mettre la
vtable
dans le cas où vous avez la définition des fonctions virtuelles d'un objet réparties sur plusieurs compilations unités (par exemple, certains des objets virtuels définition de fonctions sont dans un .fichier cpp d'autres dans un autre .fichier cpp, et ainsi de suite).Le compilateur choisit de mettre l'
vtable
à l'endroit même où le premier déclaré fonction virtuelle est définie.Maintenant si vous avez oublié de donner une définition de cette première fonction virtuelle déclaré dans l'objet (ou à tort oublié d'ajouter l'objet compilé le lien entre la phase de), vous obtiendrez cette erreur.
Comme un effet secondaire, veuillez noter qu'uniquement pour cette fonction virtuelle vous n'obtiendrez pas le traditionnel de l'éditeur de liens d'erreur comme il vous manque la fonction foo.
À ne pas franchir post mais. Si vous êtes aux prises avec héritage le second google a frappé était ce que j'avais raté, c'est à dire. toutes les méthodes virtuelles doivent être définis.
Tels que:
Voir answare C++ Undefined Reference to vtable et de l'héritage pour plus de détails. Juste de réaliser qu'il est déjà mentionné ci-dessus, mais bon, ça pourrait aider quelqu'un.
Ok, la solution est que vous avez manqué sur la définition. Voir l'exemple ci-dessous afin d'éviter la vtable erreur de compilateur:
CDasherComponent
a un corps pour le destructeur? C'est certainement pas ici la question est de savoir si il est dans le .cc fichier.CDasherModule
doit définir explicitement le destructeurvirtual
.CGameModule
a une}
à la fin (après le}; //for the class
).CGameModule
être lié à l'encontre de l'bibliothèques qui définissentCDasherModule
etCDasherComponent
?Manque peut-être le destructeur virtuel est facteur?
C'était le premier résultat de recherche pour moi donc, j'ai pensé ajouter une autre chose à vérifier: assurez-vous que la définition de fonctions virtuelles sont réellement à la classe. Dans mon cas, j'ai eu ceci:
Fichier d'en-tête:
et dans mon .cc fichier:
Cela devrait lire
Peut-être pas. Certainement
~CDasherModule() {}
est manquant.Donc beaucoup de réponses ici, mais aucun d'eux ne semblait avoir couvert ce que mon problème a été. J'ai eu la suivante:
Et dans un autre fichier (inclus dans la compilation et la liaison, bien sûr)
Bien cela n'a pas fonctionné et j'ai obtenu l'erreur, tout le monde parle. Pour le résoudre, j'ai dû déplacer la réelle définition de Foo de la déclaration de la classe en tant que telle:
Je ne suis pas du C++ guru donc je ne peux pas expliquer pourquoi c'est plus correct, mais il a résolu le problème pour moi.
J'ai donc été à l'aide de Qt avec Windows XP et le compilateur MinGW et cette chose a été me rend fou.
Fondamentalement la moc_xxx.cpp a été généré vide même quand j'ai été ajouté
Macro q_object
La suppression de tout, de prise de fonctions virtuelles, explicite et tout ce que vous devinez n'a pas travaillé. Enfin, j'ai commencé à retirer, ligne par ligne, et il s'est avéré que j'avais
Autour du fichier. Même lorsque le #ifdef est vrai moc fichier n'a pas été généré.
Donc supprimer tous les #ifdefs résolu le problème.
Cette chose ne se passait pas avec Windows et VS 2013.
g++ *.cpp ...
. (Besoin de quelque chose de rapide et sale, mais qmake était pleine de tristesse.)Si tout le reste échoue, regardez pour la duplication. J'ai été mal acheminés par la référence explicite initial de référence pour les constructeurs et destructeurs jusqu'à ce que j'ai lu une référence dans un autre post. C'est tout non résolus de la méthode. Dans mon cas, je pensais que j'avais remplacé la déclaration qui a utilisé char *xml en tant que paramètre à l'aide de la inutilement pénible const char *format xml, mais au lieu de cela, j'avais créé une nouvelle gauche et l'autre à la place.
Il y a beaucoup de possibilités mentionnées de l'origine de cette erreur, et je suis sûr que beaucoup d'entre eux font l'erreur. Dans mon cas, il y a un autre définition de la même classe, en raison d'une duplication du fichier source. Ce fichier a été établi, mais pas liés, de sorte que l'éditeur de liens se plaindre d'être incapable de le trouver.
Pour résumer, je dirais que si vous avez regardé la classe assez long et ne peut pas voir ce possible problème de syntaxe pourrait être à l'origine, optez pour des problèmes de génération comme un fichier manquant ou un dupliqué le fichier.
Dans mon cas, j'utilise Qt et avaient défini un
QObject
sous-classe dans unfoo.cpp
(pas.h
) fichier. Le correctif a été ajouter#include "foo.moc"
à la fin defoo.cpp
.J'ai eu cette erreur dans le scénario suivant
Prenons le cas où vous avez défini la mise en œuvre des fonctions membres d'une classe dans le fichier d'en-tête lui-même. Ce fichier d'en-tête est exporté en-tête (en d'autres mots, il peut être copié sur la/les inclure directement dans votre base de code). Maintenant que vous avez décidé de séparer la mise en œuvre des fonctions de membre de de .fichier cpp. Après, vous vous êtes séparé/déplacé de la mise en œuvre d' .rpc, le fichier d'en-tête a maintenant juste les prototypes des fonctions de membre à l'intérieur de la classe. Après les changements ci-dessus, si vous construisez votre base de code, vous pouvez obtenir les "undefined reference to 'vtable..." erreur.
Pour résoudre ce problème, avant de construire, assurez-vous de supprimer le fichier d'en-tête (à laquelle vous avez apporté des modifications) dans la commune/répertoire include. Aussi assurez-vous de modifier votre fichier makefile pour accueillir/ajouter le nouveau .o fichier est construit à partir de la nouvelle .rpc fichier que vous venez de créer. Lorsque vous effectuez ces étapes le compilateur/linker n'auront plus à se plaindre.
J'ai eu ce type d'erreur dans les situations où j'ai été tenté de faire le lien à un objet lorsque j'ai eu un bug qui empêchait l'objet ajouté à l'archive.
Dire que j'ai libXYZ.un que supposé avoir bioseq.o en int, mais il ne le fait pas.
J'ai une erreur:
Cela est très différente de tout ce qui précède. Je dirais que c'objet manquant dans l'archive problème.
Je pense qu'il vaut aussi la peine de mentionner que vous obtiendrez également le message lorsque vous essayez de lier à un objet de toute la classe qui a au moins une méthode virtuelle et l'éditeur de liens ne peut pas trouver le fichier.
Par exemple:
Foo.hpp:
Foo.cpp:
Compilé avec:
Et main.cpp:
Compilé et lié avec:
Donne à notre favori erreur:
Cette survenir à partir de mon undestanding becasue:
Vtable est créé par la classe au moment de la compilation
De l'éditeur de liens n'a pas accès à vtable qui est dans Foo.o
Il est également possible que vous obtenez un message comme
si vous oubliez de définir une fonction virtuelle d'une classe FakeClass1 quand vous êtes à essayer de lier un test unitaire pour une autre classe SomeClass.
Et
Dans ce cas, je vous suggère de vérifier vos faux pour class1 une fois de plus. Vous trouverez probablement que vous avez oublié de définir une fonction virtuelle
ForgottenFunc
dans votre faux de classe.J'ai eu cette erreur quand j'ai ajouté une deuxième classe à une source existante/en-tête de la paire. Deux en-têtes dans le même .h de fichier, et les définitions de fonction pour deux classes dans le même .fichier cpp.
Je l'ai fait avec succès avant, avec des classes qui sont destinés à travailler en étroite collaboration, mais apparemment ça n'a pas comme moi cette fois. Encore ne sais pas quoi, mais en les scindant en une classe par unité de compilation, il fixe jusqu'.
L'échec de la tentative:
_gui_icondata.h:
_gui_icondata.cpp:
Encore une fois, l'ajout d'une nouvelle source/en-tête de la paire et le découpage/collage de la IconWithData classe verbatim en il y a "travaillé".
J'ai eu cette erreur juste parce que le nom d'un argument du constructeur diffèrent dans le fichier d'en-tête et dans la mise en œuvre de fichier. La signature du constructeur est
et ce que j'ai écrit dans la mise en œuvre a commencé avec
donc j'ai accidentellement remplacé "pset" avec "parasite". Le compilateur se plaint de ce un et deux autres constructeurs dans lequel il n'y a pas d'erreur du tout. J'utilise g++ version 4.9.1 sous Ubuntu. Et de définir un destructeur virtuel dans cette classe dérivée ne fait pas de différence (elle est définie dans la classe de base). Je n'ai jamais constaté ce bug si je n'avais pas coller les constructeurs de corps dans le fichier d'en-tête, donc de les définir dans la classe.