Erreur Q_OBJECT jetant une référence «non définie à vtable»

J’utilise Qt Creator 2.0.1 avec Qt 4.7.0 (32 bits) sur Windows 7 Ultimate 32 bits.

Considérez le code suivant, qui est un minimum pour générer l’erreur:

class T : public QObject, public QGraphicsItem { Q_OBJECT public: T() {} QRectF boundingRect() const {return QRectF();} void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) {} }; int main() { T t; return 0; } 

Le fragment de code ci-dessus provoque les erreurs de l’éditeur de liens suivantes:

En fonction ‘T’:

référence indéfinie à `vtable for T ‘

référence indéfinie à `vtable for T ‘

Dans la fonction `~ T ‘:

référence indéfinie à `vtable for T ‘

référence indéfinie à `vtable for T ‘

Si je commente la ligne qui contient Q_OBJECT , elle comstack bien. J’ai besoin de signaux et de slots avec QGraphicsItem donc j’ai besoin de Q_OBJECT .

Quel est le problème avec le code? Merci.

C’est parce que l’unité générée par MOC n’est pas incluse dans le processus de liaison. Ou peut-être que ce n’est pas du tout généré. La première chose que je dois faire est de mettre la déclaration de classe dans un fichier d’en-tête distinct, peut-être que le système de génération n’parsing pas les fichiers d’implémentation.

Une autre possibilité est que la classe en question n’ait pas appartenu à un système de méta-object Qt (c’est-à-dire qu’elle n’avait pas de Q_OBJECT ou n’avait peut-être pas hérité de QObject), donc qmake doit être exécuté à nouveau pour créer le règles nécessaires pour MOC. La méthode la plus simple pour forcer l’exécution de qmake consiste à apporter des modifications insignifiantes au fichier de projet pour mettre à jour son horodatage, par exemple en ajoutant puis en supprimant des espaces. Ou, si vous utilisez Qt Creator, sélectionnez simplement «Exécuter qmake» dans le menu contextuel du projet.

Si vous souhaitez définir une sous-classe QObject dans un fichier source, vous devez append la ligne

 #include "file.moc" 

à un moment donné après votre définition de classe où le nom du fichier source était fichier.cpp. Vous devrez bien sûr relancer qmake afin que la règle appropriée pour exécuter moc soit ajoutée au Makefile.

Ce n’est que dans un fichier d’en-tête que la présence de Q_OBJECT dans une définition de classe entraîne l’ Q_OBJECT de Q_OBJECT . Si c’est un fichier source, vous avez besoin de cette ligne supplémentaire pour forcer l’utilisation de moc .

Je suis sûr qu’une question similaire a déjà été posée mais je ne l’ai pas trouvée.

Placez vos classes Q_OBJECT dans des fichiers séparés. C’est un .h et un .cpp pour chaque classe. Les macros de méta-object de Qt sont plutôt pointilleuses à cet égard.

En outre, vous pouvez utiliser QGraphicsObject pour votre objective. Vous économise du temps là-bas.

Edit: Je vois que vous utilisez Creator. Utilisez sa nouvelle fonction de classe C ++ dans Nouveau fichier ou projet pour créer le fichier “dans le bon sens” 🙂

Voici le code de travail ajouté avec toutes les corrections fournies dans d’autres questions (Essayé la compilation propre et l’aide de ces corrections):

 #include  class T : public QObject, public QGraphicsItem { Q_OBJECT Q_INTERFACES(QGraphicsItem) //Required. public: T() {} QRectF boundingRect() const {return QRectF();} void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) {} }; int main(int argc, char *argv[]) { T *t = new T; return 0; } #include "main.moc" // Required. 

Donc crédit réel à Troubadour et serge_gubenko

il y a quelques choses à regarder:

  1. Ajouter QT + = gui dans votre fichier pro
  2. Assurez-vous de définir vos classes dérivées de QObject dans vos fichiers d’en-tête uniquement (edit: comme Troubadour l’a noté, ce n’est pas obligatoire)
  3. Ajoutez Q_INTERFACES (QGraphicsItem) à la déclaration de votre classe T

ci-dessous est un exemple:

th:

 class T : public QObject, public QGraphicsItem { Q_OBJECT Q_INTERFACES(QGraphicsItem) public: T(); QRectF boundingRect() const; void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); }; 

t.cpp:

 T::T() {} QRectF T::boundingRect() const { return QRectF(); } void T::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { Q_UNUSED(painter); Q_UNUSED(option); Q_UNUSED(widget); } 

J’ai essayé de comstackr le code ci-dessus et je n’ai pas rencontré de problèmes.

espère que cela aide, regarde