63 votes

Q-OBJECT lancer '#39;référence indéfinie à vtable '#39; erreur

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

Considérons le code suivant, qui est un minimum pour produire 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 les causes suivantes erreurs d'édition de liens:

Dans la fonction "T":

undefined reference to `vtable for T'

undefined reference to `vtable for T'

Dans la fonction `~T':

undefined reference to `vtable for T'

undefined reference to `vtable for T'

Si je commente la ligne qui contient Q_OBJECT, il compile bien. J'ai besoin de signaux et de slots, avec QGraphicsItem j'ai donc besoin d' Q_OBJECT.

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

124voto

Sergey Tachenov Points 8123

C'est parce que l'unité généré par le MOC n'est pas inclus dans le processus de liaison. Ou peut-être qu'il n'est pas générée à tous. La première chose que je ferais est de mettre la déclaration de classe dans un autre fichier d'en-tête, peut-être le système de construction n'est pas la numérisation de fichiers de mise en œuvre.

Une autre possibilité est que la classe en question, une fois n'appartient pas à l'intervalle Qt de méta-objet système (qui est, il n'avait pas de macro q_object ou peut-être de ne pas hériter de QObject à tous), de sorte que qmake doit être exécuté à nouveau afin de créer les règles nécessaires à la MOC. La façon la plus simple de la force de qmake à exécuter est de faire quelques changements insignifiants pour le fichier de projet pour la mise à jour de sa timestamp, comme l'ajout et le retrait d'un espace vide.

24voto

Troubadour Points 9485

Si vous souhaitez définir un QObject sous-classe dans un fichier source puis vous devez ajouter la ligne

#include "file.moc"

à un certain moment après votre définition de classe d'où le nom du fichier source file.cpp. Vous aurez besoin de ré-exécuter qmake du cours, afin que la règle appropriée pour exécuter moc a été ajouté le Makefile.

Que lorsque, dans un fichier d'en-tête n'est la présence d' Q_OBJECT dans une définition de classe causer moc être invoquée. Si c'est un fichier source vous avez besoin de cette ligne supplémentaire à la force moc à être utilisé.

Je suis sûr que d'une question similaire a été posée, mais je ne pouvais pas le trouver.

8voto

Stephen Chu Points 8440

Placez vos cours de Q-OBJECT dans des fichiers distincts. C'est un .h et un .cpp pour chaque classe. Les macros méta-objets de Qt sont plutôt pointilleux à cet égard.

En outre, vous pouvez utiliser QGraphicsObject pour votre but. Ca te fait gagner du temps là-bas.

Edit: Je vois que vous utilisez Créateur. Utilisez sa nouvelle fonction classe CMD dans le nouveau fichier ou le projet pour créer le fichier de la « bonne façon » :)

6voto

Tuukka Lindroos Points 771

Voici le code de travail ajouté avec toutes les corrections fournies dans d'autres questions (Essayé de compilation propre et ces correctifs aider):

Donc crédit réel à Troubadour et serge-gubenko

4voto

serge_gubenko Points 11561

il y a quelques chose à regarder:

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

ci-dessous est un exemple:

t.h:

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 compiler le code ci-dessus et n'ai pas de problèmes avec elle.

espérons que cela aide, cordialement

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X