Qt : undefined reference to vtable for …

Publié dans C / C++ | Marqué avec , ,
Share

Si vous travaillez sur Qt, il vous ait peut-être déjà arrivé d’obtenir une erreur du style :

erreur : undefined reference to `vtable for’

Pourquoi a-t-on cette erreur ?

Cette erreur arrive généralement lorsque l’on souhaite utiliser « signal » et « slot » dans Qt via la méthode connect. Pour une raison ou une autre, le compilateur n’arrive pas à créer le ou les fichiers « .moc » nécessaire à ce mécanisme, et : c’est le drame !
Une autre raison peut être la non sur-définition d’une méthode dérivée alors qu’elle est déclarée virtual dans la classe parente. Là encore, même résultat: le compilateur n’arrive par à créer les fichiers « .moc ».
Voyons voir comment corriger tout ça…

Check-up rapide

Ce problème est parfois dû à la non recompilation de fichiers qui ont pourtant été modifiée. Cela m’arrive souvent quand j’inclue une librairie externe (librairie-maison que j’améliore de temps en temps), ou alors lorsque quelqu’un d’autre modifie des fichiers via un SVN (je pense que c’est la raison du bug que Seb détaille dans les commentaires).
Voilà pourquoi avant même de chercher mon erreur (comme indiqué dans le paragraphe ci-dessous), j’effectue souvent la manipulation suivante :

  • Clic droit sur le projet : « Nettoyer le projet ‘…' »
  • Clic droit sur le projet : « Excécuter qmake »
  • Clic droit sur le projet : « Recompiler le projet ‘…' »

Si le problème persiste : désormais, c’est sûr, c’est de votre faute ! Alors, allez lire le paragraphe suivant 🙂

Résolution

Tout d’abord, les éléments connectés doivent hériter de QObject !

#include <QObject>
//...

class <nom de votre classe> : public QObject
{
	Q_OBJECT
public:
	<nom de votre classe>
	// ...
};

Ensuite, il faut s’assurer que les classes n’ont pas été déclaré dans un .cpp (un fichier source), et que les fichiers .h (ou .hpp, un fichier d’entête) n’ont pas été oublié dans la variable HEADERS du fichier de configuration du projet .pro. Si ce n’est pas le cas :

  • Déplacer la déclaration des classes dans un fichier .h
  • Ajouter au fichier .pro :

    HEADERS += <vos fichiers .h manquants>

  • Personnellement, j’ai dû changer dans mon fichier .pro :

    HEADERS += \
    <fichier1.h> \

    <fichierN.h>

    en

    HEADERS += <fichier1.h> \

    <fichierN.h>

Logiquement cela devrait fonctionner… Toujours pas ? C’est peut-être que votre classe n’utilisait pas la macro Q_OBJECT auparavant et que vous venez de l’ajouter. Dans ce cas, relancez qmake sans paramètres pour que les fichiers .moc soient régénérés (Clic droit sur votre projet > Exécuter qmake).

Dans le cas où le problème provient d’une mauvaise déclaration / utilisation des fonctions virtual (dans le cas d’un héritage), éh bien c’est une erreur C++. Si j’ai bien compris, il ne peut y avoir qu’une vtable par classe, et ici la vtable de la classe héritée est en commun avec la classe parente, ce qui ne devrait pas être le cas vu qu’au moins une des méthodes est déclarée virtual. Bref, autant dire que je n’ai pas tout capté 😉 Pour en savoir plus, vous pouvez parcourir cette discussion sur le sujet voir vous renseigner sur les vtables C++. Quelques bonnes pratiques cependant :

  • Si vous n’avez pas besoin du virtual : ne l’utilisez pas !
  • Sinon, sur-définissez bien vos méthodes virtual dans les classes héritées.

Vous aurez peut-être besoin de relancer qmake une fois le problème corrigé.

D’autres réponses sur ce sujet

19 réponses à Qt : undefined reference to vtable for …

  1. Bob Lapique

    Je pense que la date du .pro importe plus que le changement de ligne des headers. Ca force qmake et moc et toute la bande à s’exécuter pour repartir sur de bonnes bases, e.g. si on a ajouté des Q_OBJECT, etc.

  2. Seb

    Merci pour ce billet explicatif. Cependant, j’ai eu le même problème qui s’est résolu différemment et voici la solution :
    J’utilise QtCreator; il faut savoir que QtCreator ne recompile pas tout lors de chaque demande d’exécution. Je me trouvais face à la même erreur suite à ce qu’un collègue ait fait un svn add sur le dépôt du projet.
    La solution est arrivée toute seule en supprimant le dossier de build créé par Qt lors de la compilation (qui était donc incomplet avec l’ajout des nouveaux fichiers). Ainsi, QtCreator a été obligé de recompiler la totalité du projet et je n’ai plus eu de souci.
    Bien évidemment , cette solution s’est présentée alors que les conditions que tu décris dans ton billet étaient déjà réunies!

    • Merci pour ce feedback. J’ai rajouté un paragraphe « Check-up rapide » qui permet peut-être de résoudre ce souci plus rapidement.

  3. Laurent

    Je ne peux que te dire merci: je viens d’avoir ce problème et c’est sans doute l’exécution forcée de qmake qui a tout résolu. Je cherchais désespérément dans mon code !

  4. Ping : Qt : “undefined reference to vtable for…” | Le blog-note d'Eusebius

  5. Qt_Victime

    Merci beaucoup, ça m’a sauvé d’un suicide.

  6. Joh

    Un grand merci! Ca fait je sais pas combien d’heures que je me casse la tête avec cette erreur de compil’!! Je trouvais pas ce qui clochait dans mon code alors qu’il correspondait ligne par ligne à l’exemple que j’utilisais! Thaaaaanks

  7. cestun

    merci merci merci merci merci !!!

  8. Dsant

    Génial ce post ! j’avais fait les 2 erreurs (omis Q_OBJECT et tout mis dans un unique fichier .cpp) : MERCI !

  9. Didi13

    Merci beaucoup pour cette aide, le coup de refaire QMake quand on ajoute la macro Q_OBJECT, je n’y avais pas pensé et je ne comprenais donc pas pourquoi ça ne fonctionnait pas. Un grand merci, cela m’aura éclairé sur pas mal de points sombres ! =D

  10. Merci
    Cela m’aide dans le cours c++ du sitedusero 😉

  11. Imanos

    MERCIIIIII 🙂

  12. Vous m’avez sauvé la vie Merci pour l’article !!

  13. Suerte80

    Je vous remercie pour cette article qui vient de me sauver la vie !!! :O MEEEEERCIIII !!!

  14. TizonDife

    Cool ! Merci !

  15. abib

    Merci ça ma fait gagner du temps. Je comprenais pourquoi cette erreur.

  16. dsant

    « il faut s’assurer que les classes n’ont pas été déclaré dans un .cpp (un fichier source), et que les fichiers .h (ou .hpp, un fichier d’entête) n’ont pas été oublié dans la variable HEADERS du fichier de configuration du projet .pro » : C’est tout à fait ça.
    Car pour un simple Hello World ,le réflexe est de ne pas faire de fichier .h et de tout mettre dans un .cpp unique.
    Merci !

  17. Qt_beginner

    Merci, déjà que j’ai perdu la journée à chercher :p

  18. Merci c’était très utile 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*