web-dev-qa-db-fra.com

Symbole externe non résolu "public: structure virtuelle QMetaObject const * __thiscall Parent

J'ai hérité d'une classe de QObject: 

class Parent: public QObject
{
    Q_OBJECT
    QObject* cl;

public:
    Parent(QObject *parent=0):QObject(parent) {
        cl = NULL;
    }

    QObject* getCl() const {
        return cl;
    }
    void setCl(QObject *obj) {
        cl = obj;
    }
};

Mais quand j'écris:

Parent ev;

Je reçois l'erreur suivante:

main.obj:-1: error: LNK2001: unresolved external symbol "public: virtual struct QMetaObject const * __thiscall Parent::metaObject(void)const " (?metaObject@Parent@@UBEPBUQMetaObject@@XZ)

main.obj:-1: error: LNK2001: unresolved external symbol "public: virtual void * __thiscall Parent::qt_metacast(char const *)" (?qt_metacast@Parent@@UAEPAXPBD@Z)

main.obj:-1: error: LNK2001: unresolved external symbol "public: virtual int __thiscall Parent::qt_metacall(enum QMetaObject::Call,int,void * *)" (?qt_metacall@Parent@@UAEHW4Call@QMetaObject@@HPAPAX@Z)
58

Vous devez supprimer le dossier debug de votre application et le réexécuter pour résoudre ce problème.

64

Si vous utilisez Visual Studio, supprimez la ligne Q_OBJECT du fichier d'en-tête, enregistrez le fichier, replacez Q_OBJECT dans le fichier d'en-tête, puis enregistrez à nouveau le fichier. Cela devrait générer le fichier moc_* et créer et lier correctement.

53
MPicazo

J'ai remarqué que certaines réponses sont basées sur Visual Studio.

Cette réponse est basée sur Qt Creator.

Contrairement à ce que suggère le nom, Rebuild Project n'effacera pas tout et construira à partir de zéro. Si vous avez récemment ajouté QObject (et/ou Q_OBJECT) à votre classe, vous devrez exécuter à nouveau qmake, par exemple.

  1. Projet propre
  2. Exécuter qmake
  3. Projet de construction

En effet, par défaut, qmake ne s'exécute que lorsque vous apportez des modifications importantes à votre solution, telles que l'ajout de nouveaux fichiers source ou la modification du fichier .pro. Si vous modifiez un fichier existant, il ne sait pas qu'il doit exécuter qmake.

Comme solution de rechange, pour forcer Qt à tout construire à partir de zéro, supprimez le dossier Debug ou Release.

27
Stephen Quan

Le problème était donc que j'avais besoin du compilateur Qt MOC pour compiler mon fichier .h. Ceci est requis pour toutes les classes qui étendent QObject ou l'un de ses enfants. Le correctif impliquait (pour moi) un clic droit sur le fichier d’en-tête, choisissant Propriétés, et définissant le type d’élément sur "Qt MOC Input", puis "Compiler" sur l’en-tête, puis ajoutant le fichier moc_myfilename.cpp résultant à projet.

8
Vern Jensen

Si vos fichiers moc sont générés dans le projet Visual Studio, essayez de les inclure dans le projet s'ils ne le sont pas, puis reconstruisez-les.

7
Akın Yılmaz

J'utilise CMake pour gérer les projets Qt et le nouveau Q_OBJECT doit être ajouté à l'appel QT4_WRAP_CPP. Cela générera le moc _ *. Cxx à inclure dans le projet et nettoiera les externes non résolus.

4
whatnick

J'ai eu ce problème avec Visual Studio 2012 lorsque j'avais une définition de classe Q_OBJECT dans mon fichier cpp. Le déplacement de la définition de classe dans le fichier d'en-tête a résolu le problème.

Il semble possible de prendre en charge la classe Q_OBJECT dans le fichier cpp en ajoutant le fichier cpp à moc mais je n’ai pas essayé cela.

3
Edward

J'ai ajouté manuellement des fichiers cpp/ui à mon projet, mais j'ai oublié d'ajouter explicitement le fichier d'en-tête en tant que fichier d'en-tête. Maintenant, lors de la compilation, un message d'erreur similaire à celui ci-dessus est apparu et les fichiers moc _ *. Cpp n'ont pas été générés dans le répertoire debug (ou release) de la construction. Ce n'était pas une erreur si évidente, qmake ne s'est pas plaint et à part le message de l'éditeur de liens, je n'ai pas eu d'erreur.

Donc, si quelqu'un rencontre à nouveau le même problème (ou fait la même erreur copy & pase): assurez-vous que les fichiers d'en-tête ont également été ajoutés à votre fichier de projet

2
Vinoj John Hosan

Mon problème était qu'un de mes fichiers qui utilisait une macro Qt n'a pas été mocé. J'ai découvert que le plug-in Qt pour Visual Studio ne reconnaît pas la macro Q_NAMESPACE et n'ajoute donc pas le fichier à la liste des utilisateurs potentiels.

J'ai donc utilisé la solution de cette réponse pour ajouter le fichier à la liste des micro:

Vous devriez trouver un fichier .h qui a généré avec succès "moc_ *", et copiez tout le contenu dans "Outil de construction personnalisé -> Général" sur la nouvelle page de paramétrage du fichier .h.

Soyez prudent avec les différentes options pour les modes Debug et Release-.

Après cela, construisez votre projet.

Construisez-le une fois chacun en mode Debug et Release-

Enfin, ajoutez le fichier "moc_ *" généré à votre projet.

Maintenant, "moc_filename.cpp" devrait être dans Generated Files\Debug et Generated Files\Release.

Faites un clic droit sur chacune d’elles et changez leurs propriétés:

  • Le fichier dans Debug: Modifiez la configuration en Release, puis remplacez General->Excluded from build en yes.
  • Le fichier dans Release: Modifiez la configuration en Debug, puis remplacez General->Excluded from build en yes.
1
Darkproduct

Dans mon cas (en utilisant QtAdd-in avec VS2012 et Qt v4.8.4), aucune des suggestions ci-dessus n'a fonctionné .. Pour une raison quelconque, VS n'a pas pu générer les fichiers moc appropriés (résultat de la construction: aucune classe pertinente n'a été trouvée. Aucun résultat généré.) et lorsque j'ai compilé à la main les en-têtes pertinents (paramétrer qt moc en tant que compilateur et en cliquant sur «Compiler»), il produisait un fichier moc vide. 

Ce qui a fonctionné a été de compiler tous les documents nécessaires à partir de la ligne de commande (moc -o moc_SomeClass.cpp SomeClass.h), puis de remplacer les mauvais dans le dossier GeneratedFiles.

Ce n'est qu'une solution de contournement (et pas pratique pour un grand projet) pour que votre projet soit construit avec succès, mais n'explique pas vraiment le comportement étrange VS/QtAdd-in.

1
dianull

En utilisant QtAdd-in avec VS2010, j’ai réalisé que les fichiers moc _ *. Cpp étaient mis à jour dans le dossier GeneratedFiles/Debug alors que j’étais en mode de publication. Copier les fichiers dans le dossier Release a fonctionné pour moi.

1
zengaja

J'ai rencontré ce problème avec l'utilisation d'une "classe privée" dans Qt lors de l'utilisation du modèle de programmation "PIMPL" (implémentation privée). Qt utilise ce modèle tout au long de son code source. Je viens de vraiment aimer moi-même. 

Cette technique implique l’utilisation d’une classe "privée" déclarée en aval dans un fichier d’en-tête public, qui sera utilisée par la classe "publique" (c’est-à-dire "parent"). Le parent a ensuite un pointeur sur une instance de la classe privée en tant que membre de données.

La classe "privée" est entièrement définie dans le fichier cpp du fichier public. Il n'y a AUCUN fichier d'en-tête pour la classe privée. 

Tout le "sale boulot" est fait avec cette classe privée. Cela masque toute l'implémentation de votre classe publique, y compris tous les autres membres privés (données et fonctions).

Je vous recommande vivement de vous familiariser avec le modèle PIMPL - surtout si vous lisez un jour la source Qt interne. 

Sans expliquer davantage ce style de codage, voici le point en rapport avec cette question ... Pour que la macro Q_OBJECT fonctionne dans le cpp pour que la classe "privée" soit QObject pouvant utiliser des signaux/slot, etc., vous nécessaire pour inclure explicitement le .moc à la classe publique à l'intérieur du cpp :

#include "MyPublicClass.moc"

Vous pouvez ignorer tous les avertissements IDE concernant cette ligne.

Je ne sais pas si cela a vraiment son importance, mais cette inclusion que je vois toujours se faire APRÈS la définition de classe privée, plutôt que tout en haut du cpp (comme les inclus sont généralement placés). Donc, la mise en page cpp va comme ceci:

  1. Les inclusions "normales" sont définies.
  2. La classe privée est définie.
  3. Le moc de la classe publique est #included.
  4. L'implémentation de la classe publique est définie.
1
BuvinJ

Soit la réponse fonctionne pour moi dans l'environnement VS 2013. J'ai finalement résolu le problème en supprimant le .h/. Cpp du projet et en le rajoutant. 

0
Adam Woo

Cela m'est arrivé récemment lors du passage de MingW à MSVC. J'avais une classe/structure prototypée listée en tant que classe, et MingW s'en moquait.

MSVC voit clairement une différence entre class et struct en ce qui concerne le prototypage.

J'espère que cela aidera quelqu'un d'autre un jour.

0
phyatt

Pour moi, c’est la cause: certains en-têtes ou fichiers sources non inclus dans le fichier de projet de QT.

0
Sanbrother

Je sais que cette question est très ancienne, mais elle semble toujours intéressante (je suis ici au moins 4 ou 5 fois au cours des derniers mois) et semble avoir trouvé une autre raison pour laquelle il est possible d’obtenir cette erreur.

Dans mon cas, dans le fichier d’en-tête, j’ai mal saisi:

#include "MyClass.h""

Seulement après avoir inspecté toute la sortie, j'ai découvert qu'à cette ligne, le compilateur émettait un avertissement.

Maintenant que j'ai supprimé le guillemet supplémentaire, mon QObject est parfaitement compilé!

0
Brutus

Dans mon cas, rien de ce qui précède n'a fonctionné, mais c'était totalement mon erreur.

J'avais écrasé les fonctions virtuelles dans le fichier .h (les ai déclarées) mais je ne les avais jamais définies dans le .cpp :)

0
zar

J'ai le même problème, ma solution était l'encodage (mon fichier avec "UTF16LE BOM" ne peut pas générer avec moc.exe), y créer un autre fichier avec ASCII enconding et ça marche.

HxD HexEditor peut vous aider à voir la codification.

0
Jefferson Rondan

J'ai résolu mon problème en l'ajoutant à mon fichier d'en-tête:

#ifndef MYCLASSNAME_H
#define MYCLASSNAME_H

... // all the header file content.

#endif
0
Nadjib Dz

Je travaille dans VS2015 avec un client Perforce p4v intégré . Dans mon cas, Perforce a essayé d'ajouter un fichier moc à un dépôt. Lorsque j'ai annulé cette opération, Perforce a supprimé ce fichier moc du projet et l'a supprimé . Le fichier a été recréé après la compilation suivante, mais cela n’a pas été inclus dans le projet, je dois l’ajouter manuellement aux fichiers générés, lorsque j’ai enfin compris quel était le problème.

0
Flot2011