'Référence non définie à l'erreur vtable '[dupliquer]

cette question a déjà une réponse ici:

j'utilise Qt Creator 2.0.1 avec Qt 4.7.0 (32 bit) sur Windows 7 Ultimate 32 bit.

Considérons le code suivant, qui est une 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 provoque les erreurs de linker suivantes:

dans la fonction "T":

référence non définie à 'vtable for T '

référence non définie à 'vtable for T '

en fonction '~T':

référence non définie à 'vtable for T '

Non défini référence à "vtable for T

Si je commente la ligne qui contient Q_OBJECT , il compile bien. J'ai besoin du signal et des fentes avec QGraphicsItem donc j'ai besoin de Q_OBJECT .

Qu'est-ce qui ne va pas avec le code? Grâce.

52
demandé sur Donotalo 2011-01-23 17:24:53

5 réponses

c'est parce que l'unité générée par MOC n'est pas incluse dans le processus de lien. Ou peut-être qu'il n'est pas généré. La première chose que je ferais est de mettre la déclaration de classe dans un fichier d'en-tête séparé, peut-être que le système de compilation ne scanne pas les fichiers d'implémentation.

une autre possibilité est que la classe en question n'a pas appartenu à Qt meta object system (c'est-à-dire qu'elle n'avait pas de Q_OBJECT ou n'a peut-être pas hérité de QObject du tout), donc qmake doit être lancé encore une fois afin de créer les règles nécessaires pour MOC. La manière la plus simple de forcer qmake à être exécuté est d'apporter des modifications insignifiantes au fichier du projet pour mettre à jour son horodatage, comme Ajouter puis Supprimer de l'espace blanc. Ou, si vous utilisez Qt Creator, Sélectionnez simplement "exécuter qmake" dans le menu contextuel du projet.

105
répondu Sergei Tachenov 2016-11-25 05:38:52

si vous voulez définir une sous-classe QObject dans un fichier source, vous devez ajouter la ligne

#include "file.moc"

à un moment après votre définition de classe où le nom du fichier source était file.rpc. Vous aurez besoin de relancer qmake bien sûr pour que la règle appropriée pour lancer moc soit ajoutée au Makefile.

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

je suis sûr qu'une question semblable a déjà été posée, mais je n'ai pas pu la trouver.

20
répondu Troubadour 2011-01-23 15:56:18

mettez vos classes Q_OBJECT dans des fichiers séparés. C'est l'un .h et un .rpc pour chaque classe. Les macros meta-object de Qt sont un peu difficiles à cet égard.

aussi, vous pouvez utiliser QGraphicsObject pour votre but. Vous permet d'économiser un certain temps.

Edit: je vois que vous utilisez Creator. Utilisez sa nouvelle fonction de Classe C++ dans nouveau fichier ou projet pour créer le fichier de la "bonne façon":)

5
répondu Stephen Chu 2011-01-23 15:18:02

voici le code de travail ajouté avec toutes les corrections fournies dans les autres questions (la compilation propre essayée et l'aide de ces corrections):

#include <QGraphicsItem>

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.

Sorte de crédit de Troubadour et serge_gubenko

5
répondu Tuukka Lindroos 2011-01-23 21:14:26

il y a quelques chose à 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 seulement (edit: comme Troubadour l'a noté, ce n'est pas nécessaire)
  3. ajouter Q_INTERFACES (QGraphicsItem) à la déclaration de votre classe T

ci-dessous 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 je n'ai pas eu de problèmes avec lui.

espère que cette aide, en ce qui concerne les

3
répondu serge_gubenko 2011-01-23 16:00:24