Symbole externe non résolu dans les fichiers objets

188

Pendant le codage dans Visual Studio, j'ai rencontré une erreur de symbole externe non résolue et je ne sais pas quoi faire. Je ne sais pas ce qui ne va pas. Pourriez-vous s'il vous plaît me déchiffrer? Où dois-je rechercher quel type d'erreurs?

1>Form.obj : error LNK2019: unresolved external symbol "public: class Field * __thiscall Field::addField(class Field *)" (?addField@Field@@QAEPAV1@PAV1@@Z) referenced in function "public: void __thiscall Form::parse(class std::basic_stringstream<char,struct std::char_traits<char>,class std::allocator<char> > &)" (?parse@Form@@QAEXAAV?$basic_stringstream@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z)
1>Form.obj : error LNK2019: unresolved external symbol "public: virtual void __thiscall Field::parse(class std::basic_stringstream<char,struct std::char_traits<char>,class std::allocator<char> > &)" (?parse@Field@@UAEXAAV?$basic_stringstream@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) referenced in function "public: __thiscall InputField::InputField(class std::basic_stringstream<char,struct std::char_traits<char>,class std::allocator<char> > &)" (??0InputField@@QAE@AAV?$basic_stringstream@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z)
1>Form.obj : error LNK2001: unresolved external symbol "public: virtual void __thiscall Field::prompt(void)" (?prompt@Field@@UAEXXZ)
1>Form.obj : error LNK2001: unresolved external symbol "public: virtual class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __thiscall Field::getName(void)" (?getName@Field@@UAE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ)
1>Form.obj : error LNK2001: unresolved external symbol "public: virtual class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __thiscall Field::getType(void)" (?getType@Field@@UAE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ)
1>Form.obj : error LNK2001: unresolved external symbol "public: virtual void __thiscall Field::describe(void)" (?describe@Field@@UAEXXZ)
1>C:\Users\tomy\Documents\Visual Studio 2010\Projects\zapoctovkac++\Debug\zapoctovkac++.exe : fatal error LNK1120: 6 unresolved externals
Novellizator
la source
27
Un symbole non résolu est un symbole que vous avez déclaré quelque part mais que vous n'avez jamais défini. Habituellement, cela signifie que vous #incluez le fichier d'en-tête d'une bibliothèque tierce mais que vous n'avez pas indiqué à l'éditeur de liens où trouver les fichiers .obj correspondants pour la bibliothèque.
deong
7
Une erreur assez courante est que vous définissez une fonction comme une fonction autonome et que vous oubliez le sélecteur de classe dans votre fichier .cpp : Vous faites ceci (faux): void myFunc() { /* do stuff */ } Au lieu de cela (à droite): void A::myFunc() { /* do stuff */ }
jave.web
Vous pouvez également ajouter des parenthèses , directement dans votre tête fichier si vous ne voulez pas définir plus dans votre fichier .cpp, comme ça: void myFunc() {};.
Patapoom
@deong Comment dites-vous à l'éditeur de liens où trouver les fichiers .obj correspondants et où se trouvent-ils habituellement?
Matt Arnold le

Réponses:

313

Cette erreur signifie souvent qu'une fonction a une déclaration, mais pas une définition.

Exemple:

// A.hpp
class A
{
public:
  void myFunc(); // Function declaration
};

// A.cpp

// Function definition
void A::myFunc()
{
  // do stuff
}

Dans votre cas, la définition est introuvable. Le problème peut être que vous incluez un fichier d'en-tête, qui apporte des déclarations de fonction, mais vous:

  1. ne définissez pas les fonctions dans votre fichier cpp (si vous avez écrit ce code vous-même)
  2. n'incluez pas le fichier lib / dll qui contient les définitions

Une erreur courante est que vous définissez une fonction comme autonome et oubliez le sélecteur de classe, par exemple A::, dans votre fichier .cpp :

Faux: void myFunc() { /* do stuff */ }
Droite: void A::myFunc() { /* do stuff */ }

Chris Morris
la source
2
Comment inclure ledit fichier lib dans mon projet?
tmj
@tMJ Cela dépend de l'environnement que vous utilisez. Je chercherais des tutoriels en ligne ou sur ce site.
Chris Morris
@ChrisMorris La définition de la fonction n'était pas disponible non pas parce que je ne l'ai pas liée correctement ou quelque chose. Mais, parce que la dll n'était pas en mémoire et devait être chargée via un appel LoadLibrary. (FTR)
tmj
2
Le dernier conseil était exactement le problème ici. Je faisais void myFunc() {}au lieu de A::void myFunc() {}.
Charles
Réponse géniale. J'avais en fait oublié à la fois (1) puis la partie A :: après avoir copié la méthode depuis ailleurs.
RoG
27

Vérifiez que vous incluez tous les fichiers source dans votre solution que vous référencez.

Si vous n'incluez pas le fichier source (et donc l'implémentation) de la classe Fielddans votre projet, il ne sera pas construit et vous ne pourrez pas créer de lien lors de la compilation.

Sinon, peut-être que vous utilisez une bibliothèque statique ou dynamique et avez oublié de dire à l'éditeur de liens les .libs?

Konrad
la source
4
La référence aux fichiers lib corrects a résolu le problème. Utilisez Project-> Properties-> Linker-> General-> Additional Library Directories and Project-> Properties-> Linker-> Input-> Additional Dependencies pour faire référence au répertoire lib et aux fichiers lib
zak
Dans mon cas, un simple \dans le fichier * .pro du projet Qt manquait (aurait dû être SOURCES += main.cpp \pour continuer à la ligne suivante).
Top-Master
11

Il semble qu'il manque une bibliothèque ou une inclusion, vous pouvez essayer de déterminer quelle classe de votre bibliothèque contient getName, getType, etc. et la mettre dans le fichier d'en-tête ou en utilisant #include.

De même, si ceux-ci proviennent d'une bibliothèque externe, assurez-vous d'y faire référence dans votre fichier projet. Par exemple, si cette classe appartient à un abc.lib alors dans votre Visual Studio

  1. Cliquez sur Propriétés du projet.
  2. Accédez aux propriétés de configuration, C / C ++, générer, vérifiez que vous pointez vers l'emplacement abc.lib sous les répertoires d'inclusion supplémentaires. Sous Linker, Input, assurez-vous que vous avez l'abc.lib sous Additional Dependencies.
Fylix
la source
10

Je viens de voir le problème que je ne peux pas appeler une fonction de main dans le fichier .cpp, correctement déclarée dans le fichier .h et définie dans le fichier .c. Une erreur de l'éditeur de liens a été rencontrée. En attendant, je peux appeler la fonction à partir du fichier .c habituel. Cela dépend peut-être de la convention d'appel. La solution consistait à ajouter les lignes de préproc suivantes dans chaque fichier .h:

#ifdef __cplusplus
extern "C"
{
#endif

et ceux-ci à la fin

#ifdef __cplusplus
}
#endif
Alexey257
la source
7

J'ai eu une erreur où mon projet a été compilé en tant que projet x64 . et j'ai utilisé une bibliothèque compilée en x86 .

J'ai recompilé la bibliothèque en x64 et cela l'a résolu.

Gal Bracha
la source
5

Parfois, si un nouveau fichier d'en-tête est ajouté et que cette erreur commence à se produire, vous devez également ajouter une bibliothèque pour vous en débarrasser unresolved external symbol.

par exemple:

#include WtsApi32.h

aura besoin:

#pragma comment(lib, "Wtsapi32.lib") 
Shashank
la source
5

J'ai eu les mêmes erreurs de lien, mais à partir d'un projet de test qui faisait référence à une autre dll. J'ai découvert qu'après avoir ajouté _declspec(dllexport)devant chaque fonction spécifiée dans le message d'erreur, le lien fonctionnait bien.

moiJustAndrew
la source
Cette réponse fait référence à une bonne solution, mais semble incomplète (et erronée car il y a deux traits de soulignement __declspec). Si dans un autre module, vous devrez importer les symboles (avec __declspec(dllimport)et non les exporter. Voir la solution complète dans cette réponse
PJ127
3

Je crois que la plupart des points concernant les causes et les remèdes ont été traités par tous les contributeurs de ce fil. Je veux juste souligner que mon problème `` externe non résolu '' a été causé par un type de données défini comme une macro qui est remplacé différemment que prévu, ce qui entraîne la fourniture de ce type incorrect à la fonction en question, et puisque la fonction avec le type n'est jamais défini, il n'aurait pas pu être résolu. En particulier, sous C / C ++ -> Langage, il existe un attribut appelé «Traiter WChar_t comme un type intégré», qui aurait dû être défini comme «Non (/ Zc: wchar_t-)» mais pas dans mon cas.

Patrick Nguyen
la source
merci, cela provoque le problème de ma configuration ('No (/ Zc: wchar_t-)')
Noypi Gilas
2

En plus de l'excellente réponse de Chris Morris ci-dessus, j'ai trouvé un moyen très intéressant de recevoir ce même défaut si vous appelez une méthode virtuelle qui n'a pas été définie sur pure mais qui n'a pas sa propre implémentation. C'est exactement la même raison (le compilateur ne peut pas trouver une implémentation de la méthode et donc des escrocs), mais mon IDE n'a pas détecté cette faute du tout.

par exemple, le code suivant obtiendrait une erreur de compilation avec le même message d'erreur:

//code testing an interface
class test
{
   void myFunc(); 
}

//define an interface
class IamInterface
{
    virtual void myFunc();
}

//implementation of the interface
class IamConcreteImpl
{
    void myFunc()
    {
       1+1=2;
    }
}

Cependant, changer IamInterface myFunc () pour qu'il soit une méthode virtuelle pure (une méthode qui "doit" être implémentée, celle qu'une méthode virtuelle qui est une méthode le "peut" être surchargée) éliminera l'erreur de compilation.

//define an interface
class IamInterface
{
    virtual void myFunc() = 0;
}

J'espère que cela aidera la prochaine personne StackOverFlow à parcourir le code!

GMLewisII
la source
2

Assurez-vous de décorer vos fichiers d'en-tête avec

#ifndef YOUR_HEADER_H
#define YOUR_HEADER_H

// your header code here

#endif

De mauvaises choses - y compris cela - peuvent arriver si vous ne le faites pas

Panouden
la source
10
Que diriez-vous d'utiliser #pragma once?
Allen Linatoc
2

Encore un autre problème possible (sur lequel je viens de me gratter la tête pendant un certain temps):

Si vous définissez vos fonctions comme inline, elles - bien sûr! - doivent être définies dans l'en- tête (ou dans un fichier en ligne ), pas dans un cpp .
Dans mon cas, ils étaient dans un fichier en ligne, mais seulement parce qu'ils étaient une implémentation spécifique à la plate-forme, et un cpp incluait ce fichier inl correspondant ... au lieu d'un en-tête. Ouais, ça arrive.

Je pensais que je laisserais cela ici aussi, peut-être que quelqu'un d'autre rencontre le même problème et le trouve ici.

Johann Studanski
la source
2
À quiconque a voté contre ceci: laissez au moins un commentaire expliquant pourquoi vous pensez que la réponse est fausse ou inutile. Un vote négatif sans commentaire ne vaut au mieux rien.
Johann Studanski
1

J'ai juste eu du mal avec ça. Tout était logiquement mis en place. J'ai déclaré un constructeur mais je ne l'ai pas défini

class SomeClass
{
   SomeClass();  // needs the SomeClass::SomeClass(){} function defined somewhere, even here
}

J'ai failli me cogner la tête sur mon clavier en oubliant quelque chose d'aussi élémentaire.

Joe Plante
la source
1

Je fais du C ++ pour la première fois depuis longtemps, et j'obtiens cette erreur lorsque j'oublie d'ajouter le préfixe ClassName :: pour la définition de la fonction, car c'est un peu unique à C ++. Alors n'oubliez pas de vérifier cela aussi!

Matthew Hayes
la source
1

Une cause possible de cette erreur de l'éditeur de liens peut également être des inlinefonctions qui sont déclarées mais non définies dans un fichier d'en-tête qui est ensuite inclus ailleurs. Les fonctions en ligne doivent être définies dans chaque unité de traduction dans laquelle elles sont utilisées.

bweber
la source
1

Cette erreur peut être provoquée en plaçant les définitions de fonction pour une classe de modèle dans un fichier .cpp distinct. Pour une classe modèle, les fonctions membres doivent être déclarées dans le fichier d'en-tête. Vous pouvez résoudre le problème en définissant les fonctions membres en ligne ou juste après la définition de classe dans le fichier .h.

Par exemple, au lieu de placer les définitions de fonction dans un fichier .cpp comme pour les autres classes, vous pouvez les définir en ligne comme ceci:

template<typename T>
MyClassName {
  void someFunction() {
    // Do something
    ...
  }
  void anotherFunction() {
    // Do something else
    ...
  }
}

Ou vous pouvez les définir après la définition de la classe mais dans le même fichier, comme ceci:

template<typename T>
MyClassName {
  void someFunction();
  void anotherFunction();
}

void MyClassName::someFunction() {
  // Do something
  ...
}
void MyClassName::anotherFunction() {
  // Do something else
  ...
}

Je pensais juste partager cela car personne d'autre ne semble avoir mentionné les classes de modèles. C'était la cause de l'erreur dans mon cas.

Joshua RC
la source
0

POINTEURS

J'ai eu ce problème et je l'ai résolu en utilisant un pointeur. Je vois que ce n'était pas votre problème, mais j'ai pensé que je le mentionnerais parce que j'aurais bien aimé qu'il soit ici quand j'ai vu cela il y a une heure. Mon problème était de déclarer une variable membre statique sans la définir (la définition devait venir après d'autres configurations) et bien sûr, un pointeur n'a pas besoin d'une définition. Erreur également élémentaire: P

Rabel
la source
3
Un exemple serait très utile ici.
moffeltje
0

Mon problème était qu'un sconscript n'avait pas le cppfichier défini. Cela peut être très déroutant car Visual Studio a le cppfichier dans le projet mais quelque chose d'autre est entièrement en cours de construction.

ubershmekel
la source
0

Mon problème était le suivant: je devais faire une déclaration en avant de la classe dont le ctor était "externe non résolu".

Dans le fichier où j'ai eu l'erreur, j'ai dû mettre quelque chose comme ceci:

#include "ClassB" 

class ClassB; // this solved the problem

class ClassA{
    void foo(){
        ClassB* tmp = new ClassB();
        // ...
    }
};

Bien sûr, mon projet est beaucoup plus compliqué et ce n'est qu'un extrait de code. Lorsque vous utilisez des espaces de noms, déclarez-les également .

Vicrucann
la source
0

Je viens de passer quelques heures à découvrir que le problème était que mon fichier principal avait une extension .cau lieu de.cpp

:/

Madhur
la source
0

Encore une autre possibilité à vérifier, c'était mon problème cette fois.

J'avais ajouté la fonction à la bibliothèque et inclus le dossier de sortie de la bibliothèque dans le chemin de recherche.

Mais j'avais aussi un dossier avec une ancienne version de la bibliothèque répertoriée auparavant, donc VS utilisait l'ancienne bibliothèque et, bien sûr, ne trouvait pas la nouvelle fonction.

Francesco Dondi
la source
0

Assurez-vous que vous n'essayez pas de surcharger les opérateurs d'insertion ou d'extraction en tant que fonctions en ligne. J'ai eu ce problème et il n'a disparu que lorsque j'ai supprimé ce mot-clé.

Beck
la source
0

Qu'est-ce qui l'avait causé dans mon cas:

J'avais un gros fichier Foo.cppsans Foo.h. Foo.cppa commencé comme ceci:

// ... 100 LOC here ...
namespace NS {
// ... 100 more LOC here ...
static int var;

J'ai supprimé le mot-clé "statique" et ajouté un Foo.havec ceci:

extern int var;

Voyez-vous l'erreur?

J'ai totalement manqué que var a été initialement défini dans un espace de noms, car la déclaration d'espace de noms a été enterrée dans un autre code. Le correctif est de changer l'externe comme ceci:

namespace NS {
     extern int var;
}
Stefan Monov
la source
0

Une raison possible de l'erreur «Symbole externe non résolu» peut être la convention d'appel de fonction.

Assurez-vous que tous les fichiers source utilisent le même standard (.c ou .cpp), ou spécifiez la convention d'appel.

Sinon, si un fichier est un fichier C (source.c) et un autre fichier est un fichier .cpp, et qu'ils sont liés au même en-tête, l'erreur «symbole externe non résolu» sera générée, car la fonction est d'abord définie comme une fonction C cdecl, mais un fichier C ++ utilisant le même en-tête recherchera une fonction C ++.

Pour éviter «l'erreur de symbole externe non résolue», assurez-vous que la convention d'appel de fonction est conservée parmi les fichiers qui l'utilisent.

Flavio
la source
0

Je suis venu ici à la recherche d'une explication possible avant de regarder de plus près les lignes précédant l'erreur de l'éditeur de liens. Il s'est avéré qu'il s'agissait d'un exécutable supplémentaire pour lequel la déclaration globale manquait!

Jerry Miller
la source
-1

J'ai juste eu la même erreur et j'arrive à l'éviter en remplaçant ;par {}dans le fichier d'en-tête.

#ifndef XYZ_h
#define XYZ_h
class XYZ
{
    public:
    void xyzMethod(){}
}
#endif

Quand c'était le cas, void xyzMethod();il ne voulait pas compiler.

Lisedra
la source