Une raison possible est que vous déclarez une fonction virtuelle sans la définir.
Lorsque vous le déclarez sans le définir dans la même unité de compilation, vous indiquez qu'il est défini ailleurs - ce qui signifie que la phase de liaison essaiera de le trouver dans l'une des autres unités de compilation (ou bibliothèques).
Voici un exemple de définition de la fonction virtuelle :
virtual void fn() { /* insert code here */ }
Dans ce cas, vous attachez une définition à la déclaration, ce qui signifie que l'éditeur de liens n'a pas besoin de la résoudre ultérieurement.
La ligne
virtual void fn();
déclare fn()
sans le définir et provoquera le message d'erreur que vous avez demandé.
C'est très similaire au code :
extern int i;
int *pi = &i;
qui stipule que le nombre entier i
est déclarée dans une autre unité de compilation qui doit être résolue au moment de la liaison (autrement pi
ne peut pas être réglé sur son adresse).
51 votes
Je sais que c'est un vieux post, mais j'ai eu le même problème aujourd'hui, et la solution était simplement de définir ma fonction virtuelle comme virtual abc() {} dans la classe de base, au lieu de virtual abc() ; qui donnait l'erreur.
31 votes
Mieux encore comme
virtual void abc() =0;
(si la version de base n'est jamais appelée)3 votes
@Nav : Si vous définissez
abc()
comme ça, vous pouvez facilement oublier de redéfinirabc()
dans la classe dérivée et penser que tout va bien, puisque vous pourrez toujours appeler la fonction sans problème. Une bonne pratique pour l'implémentation de fonctions virtuelles pures se trouve dans cet article Le but est de faire en sorte que la fonction imprime "Pure virtual function called" et fasse planter le programme.1 votes
J'avais la même erreur. j'ai découvert que changer l'ordre des références à la "lib" peut aider. j'ai juste déplacé les libs problématiques du début à la fin de la liste et cela a résolu le problème.
3 votes
GAH. C'est maintenant au moins la deuxième fois que je navigue exactement vers cette page, pour lire le commentaire de @dhardy et me dire 'Doh'. Je viens de passer 45 minutes à essayer de retrouver un comportement fou et tout ce dont j'avais besoin, c'était de
= 0;
.1 votes
Dans mon cas, j'ai changé le destructeur de base de = 0 ; à {} ;. Ensuite, tout s'est bien passé. Si vous rendez un destructeur virtuel, vous devez toujours le définir dans la classe de base. Parce que le destructeur de la classe dérivée appelle le destructeur de la classe de base pendant la destruction. Il n'a pas pu trouver la définition.