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
- « undefined reference to ‘vtable for …’ errors » in Qt derived classes (erreur avec QObject)
- Qt: Signals and slots Error: undefined reference to vtable for (erreur avec QObject)
- Discussion sur « Undefined reference to ‘vtable’ for …' » (erreur avec virtual)
Ping : Qt : “undefined reference to vtable for…” | Le blog-note d'Eusebius