Qt: un manque vtable signifie généralement que le premier non-inline fonction membre virtuelle n'a pas de définition
Il y a de nombreux fils sur tout ceci. Aucun ne semble correspondre à mon projet de loi. Je suis les liens suivante erreurs dans mon code:
Undefined symbols for architecture x86_64:
"vtable for MSFSPlugin::MSFSPluginImpl", referenced from:
MSFSPlugin::MSFSPluginImpl::MSFSPluginImpl(QObject*) in MSFSPlugin.o
MSFSPlugin::MSFSPluginImpl::~MSFSPluginImpl() in MSFSPlugin.o
NOTE: a missing vtable usually means the first non-inline virtual member function has no definition.
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Il doit avoir été quelque chose d'évident qu' - un manque vtable signifie généralement que le premier non-inline fonction membre virtuelle n'a pas de définition. Cependant, je ne vois pas ce que je suis absent:
J'ai cette classe declation dans MSFSPlugin.h
:
class MSFSPlugin
:
public QObject,
public IMediaSource
{
Q_OBJECT
Q_INTERFACES(IMediaSource)
...
protected:
class MSFSPluginImpl;
MSFSPluginImpl* mImpl;
}
Puis dans MSFSPlugin.cpp
, j'ai le texte suivant:
class MSFSPlugin::MSFSPluginImpl : public QThread
{
Q_OBJECT
public:
MSFSPluginImpl(QObject *parent = 0);
virtual ~MSFSPluginImpl();
QString getSourceDirectory() const;
void setSourceDirectory(QString sourceDirectory);
signals:
void loadDirectoryFinished(bool success);
protected:
QString mSourceDirectory;
};
Suivie par les définitions:
MSFSPlugin::MSFSPluginImpl::MSFSPluginImpl(QObject *parent) : QThread(parent)
{
}
MSFSPlugin::MSFSPluginImpl::~MSFSPluginImpl()
{
}
QString MSFSPlugin::MSFSPluginImpl::getSourceDirectory() const
{
return mSourceDirectory;
}
void MSFSPlugin::MSFSPluginImpl::setSourceDirectory(QString sourceDirectory)
{
mSourceDirectory = sourceDirectory;
}
...
En bref, je ne pense pas que je suis absent toute non en ligne virtuel membre de la définition de la fonction. Je suis à l'aide d':
Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn)
Target: x86_64-apple-darwin13.1.0
Thread model: posix
Informations Supplémentaires:
Dans mon moc_MSFSPlugin.cpp
je ne vois pas l'générée automatiquement Q_OBJECT
connexes de code pour la classe MSFSPlugin::MSFSPluginImpl
qui indirectement (par l'intermédiaire de QThread) découle de QObject
. Plus précisément, je ne vois pas le code généré pour le signal, a déclaré dans la classe (loadDirectoryFinished
). Serait-ce le problème?
EDIT 1:
L'erreur disparaît si je commentaire Q_OBJECT
de la declation de MSFSPlugin::MSFSPluginImpl
, mais alors je perds le signal de la fonctionnalité.
EDIT 2:
Je vois moc fonctionne sur les fichiers d'en-tête uniquement. Cela pourrait-il être lié au fait que ma classe dérivée de QObject est déclaré & définie dans un .fichier cpp?
MSFSPluginImpl
(parce que c'est dans un .fichier cpp). La création d'un en-tête de pour les il devrait résoudre votre problème.Lol. Je suppose que j'ai fait. Merci pour la confirmation.
double possible de la Compilation de QObject classe dérivée sur la ligne de commande sur Linux
Je pense que c'est un peu injuste pour marquer cela comme un double d'un post qui est intitulé "Compilation de QObject, dérivées de la classe sur la ligne de commande sur Linux"
il y a beaucoup de questions autour de vtables que nous avons besoin de marquer les doublons pour éviter le bruit. Si le titre est trompeur pour vous, n'hésitez pas à modifier, mais aussi loin que je peux dire, la cause de celles-ci est la même quelques-unes des raisons qui peuvent être énumérés dans un canoniques.
OriginalL'auteur Code Poet | 2014-05-11
Vous devez vous connecter pour publier un commentaire.
en Supposant que nous sommes face à des
qmake
.Les règles d'or sont:
Q_OBJECT
macro est présent dans la définition de tous lesQObject
les classes dérivées.QObject
classes dérivées dans vos fichiers d'en-tête seulement.HEADERS=
liste.qmake
chaque fois que vous ajoutezQ_OBJECT
à l'une de vos classes ou de modifier votre.pro
fichier.Explication
Yup.
Q_OBJECT
est nécessaire pour la déclaration des signaux, les machines à sous, invokables,qobject_cast
, les traductions, les propriétés, les énumérations et les méthodes d'introspection, et ainsi de suite.Le n ° 1 de la règle d'or vient du fait que sans
Q_OBJECT
vous ne pouvez pas utiliser des trucs commeqobject_cast
sur votre classe; si vous utilisez (même indirectement) l'introspection des installations, par exemple pour le débogage d'une hiérarchie d'objets ou à vidage de toutes les connexions actives à un objet, puis les objets de votre classe aurez le nom de la classe montré (et pas celui de la super-classe); etc ...Q_OBJECT
fait deux choses:moc
, dont le travail est de générer un code supplémentaire de la catégorie. Ce code permet de fournir tous les équipements mentionnés ci-dessus;qt_metacall()
etmetaObject()
.moc
va générer la mise en œuvre de ces virtuals.L'erreur que vous obtenez est le symptôme typique d'avoir déclaré l'virtuals (parce que la macro a été élargi dans votre code), mais
moc
n'était pas l'exécuter, vous avez eu quelques mises au placard virtuals qui fera le lien entre l'échec.gcc GNU ld, vous obtenez même une plus cryptique erreur, sur un
undefined reference to vtable for ClassName
. Bien sûr, googler ces erreurs vont immédiatement vous dire comment résoudre le problème.Donc, la question est: pourquoi n'était-ce pas
moc
exécuter sur un fichier qui contient la définition d'une classe avec leQ_OBJECT
macro?Lorsque nous utilisons
qmake
pour générer le Makefile, puis qmake va scanner tous les fichiers d'en-tête figurant dans leHEADERS
variable. Quand il constate qu'un en-tête contient une définition de classe avec leQ_OBJECT
macro, il sera également émettre des instructions (dans le Makefile) pour exécutermoc
sur cet en-tête, de compilermoc
, la production et le lien de l'objet résultant de la cible finale.Et nous avons des règles #2, #3, #4 ici.
n ° 2 nous dit de nous mettre
Q_OBJECT
classes dans les en-têtes; et c'est parce queHEADERS
les en-têtes de listes, pas de sources.n ° 3 nous dit, en effet, mettre tous les en-têtes dans le
HEADERS
liste. Que, évidemment, parce que si un en-tête contenant unQ_OBJECT
n'est pas dans la liste, puisqmake
de ne pas le trouver et émettent les règles. (Bien que pas strictement nécessaires pour les en-têtes ne contenant pas de QObject, sous-classes, c'est une bonne pratique à mettre chaque en-tête là pour oublier aucun.)n ° 4 nous dit de ré-exécuter
qmake
chaque fois que nous ajoutonsQ_OBJECT
ou de modifier le.pro
fichier. La raison pour la première partie de la règle est que siqmake
déjà scanné un en-tête et n'a trouvé aucuneQ_OBJECT
, alors il n'émet pas de règles dans le fichier Makefile. Mais l'ajout deQ_OBJECT
également besoin de ces règles; par conséquent, nous avons besoin deqmake
de ré-analyser les en-têtes, et c'est précisément ce que la ré-exécution deqmake
.La même raison s'applique lorsque le
.pro
est modifié (par exemple, lors de l'ajout de nouveaux en-têtes, peut-être avecQ_OBJECT
sousHEADERS
).Notez que si vous utilisez GNU-comme
make
, puisqmake
va émettre une règle spéciale qui ditmake
pour ré-exécuterqmake
puis redémarrez le Makefile, si le.pro
se modifie après le Makefile. C'est pourquoi généralement sur UNIX, vous n'avez pas besoin d'exécuter de nouveau manuellementqmake
lorsque vous modifiez votre.pro
-- juste en cours d'exécutionmake
sera également exécuterqmake
de nouveau. Mais cela ne fonctionne pas partout.Donc, est-il impossible d'avoir la définition de classes contenant
Q_OBJECT
dans un.cpp
fichier?Non, il est parfaitement possible, mais il nécessite l'utilisation d'un en quelque sorte sans-papiers
qmake
fonctionnalité. L'astuce est d'ajouter une ligne comme:à la fin de la
foobar.cpp
fichier, un fichier qui contient un ou plusieurs définitions de classe avecQ_OBJECT
.qmake
trouverez cette spéciale de l'inclusion et de générer une règle pourmoc
pour créerfoobar.moc
, qui sera ensuite repris par la.cpp
et donc compilé avec elle. (Il n'y aura donc pas de règles supplémentaires pour la compilationfoobar.moc
ni pour lier le résultat.)Juste une question de suivi. Je travaille essentiellement dans QtCreator. Si j'utilise le
rebuild
de commande, ne pas courirqmake
de nouveau ou dois-je exécuter manuellementqmake
?questions un
make clean
, puisqmake
, puismake
. C'est, il fera l'affaire, mais au prix de recompiler l'ensemble de votre projet (!). C'est pourquoi il y a un explicite "exécuter qmake" entrée dans le menu de construction.l'exécution de qmake a résolu le problème
OriginalL'auteur peppe
Oui, la macro q_object est nécessaire pour les signaux, les fentes, les propriétés et ainsi de suite.
Oui et non. Je vais vous expliquer..
Généralement, il est résolu que par la séparation que vous écrivez, mais il est également possible d'inclure le moc fichier après votre définition de classe pour le faire fonctionner, mais vous devez vous rappeler de ne pas mettre plus d'un dans la là pour éviter d'étranges conséquences.
Donc, dans votre cas, vous pourriez établir un
MSFSPlugin_p.h
ouMSFSPluginImpl.h
fichier pour la mise en œuvre de l'en-tête.Par la voie, c'est une mauvaise idée de faire pimpl protégé. Le pimpl idiome signifie privé mise en œuvre, ne sont pas protégés.
cela est bien, ne vous inquiétez pas.
OriginalL'auteur lpapp