Simbolo esterno non risolto nei file oggetto


180

Durante la programmazione in Visual Studio ho ricevuto un errore di simbolo esterno non risolto e non ho idea di cosa fare. Non so cosa c'è che non va. Potresti per favore decifrarmi? Dove dovrei cercare che tipo di errori?

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

26
Un simbolo non risolto è un simbolo che hai dichiarato da qualche parte ma che non hai mai definito. Di solito, significa che hai incluso # il file di intestazione di una libreria di terze parti ma non hai detto al linker dove trovare i file .obj corrispondenti per la libreria.
deong

7
L'errore abbastanza comune è che definisci una funzione come autonoma e dimentichi il selettore di classe nel tuo file .cpp : fai questo (sbagliato): void myFunc() { /* do stuff */ } invece di questo (a destra): void A::myFunc() { /* do stuff */ }
jave.web

È inoltre possibile aggiungere parentesi direttamente in intestazione del file se non si desidera definire più nel file cpp, così: void myFunc() {};.
Patapoom,

Risposte:


303

Questo errore spesso indica che alcune funzioni hanno una dichiarazione, ma non una definizione.

Esempio:

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

// A.cpp

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

Nel tuo caso, la definizione non può essere trovata. Il problema potrebbe essere che stai includendo un file di intestazione, che porta in alcune dichiarazioni di funzione, ma tu:

  1. non definire le funzioni nel tuo file cpp (se hai scritto tu stesso questo codice)
  2. non includere il file lib / dll che contiene le definizioni

Un errore comune è che si definisce una funzione come standalone e si dimentica il selettore di classe, ad esempio A::nel file .cpp :

Sbagliato: void myFunc() { /* do stuff */ }
giusto: void A::myFunc() { /* do stuff */ }


2
Come includere il suddetto file lib nel mio progetto?
tmj

@tMJ Dipende dall'ambiente in uso. Cercherei tutorial online o su questo sito.
Chris Morris,

@ChrisMorris La definizione della funzione non era disponibile non perché non l'ho collegata correttamente o qualcosa del genere. Tuttavia, poiché la dll non era in memoria e doveva essere caricata tramite una chiamata LoadLibrary. (FTR)
tmj

2
L'ultimo consiglio è stato esattamente il problema qui. Stavo facendo void myFunc() {}invece di A::void myFunc() {}.
Charles,

Risposta brillante. In realtà avevo dimenticato sia (1) che poi la parte A :: dopo aver copiato il metodo da altrove.
RoG

24

Verifica di includere tutti i file di origine nella soluzione a cui fai riferimento.

Se non includi il file sorgente (e quindi l'implementazione) per la classe Fieldnel tuo progetto, questo non verrà creato e non potrai collegarti durante la compilazione.

In alternativa, forse stai usando una libreria statica o dinamica e hai dimenticato di dire al linker della .libs?


3
Il riferimento ai file lib corretti ha risolto il problema. Usa Progetto-> Proprietà-> Linker-> Generale-> Directory librerie aggiuntive e Progetto-> Proprietà-> Linker-> Input-> Dipendenze aggiuntive per fare riferimento alla directory lib e ai file lib
zak

11

Sembra che manchi una libreria o includa, puoi provare a capire quale classe della tua libreria che ha getName, getType ecc ... e inserirla nel file di intestazione o usando #include.

Inoltre, se questi provengono da una libreria esterna, assicurati di fare riferimento a loro nel tuo file di progetto. Ad esempio, se questa classe appartiene a un abc.lib, quindi in Visual Studio

  1. Fai clic su Proprietà progetto.
  2. Vai a Proprietà di configurazione, C / C ++, Genera, verifica di puntare alla posizione abc.lib in Directory di inclusione aggiuntive. In Linker, Input, assicurati di avere abc.lib in Dipendenze aggiuntive.

9

Ho appena visto il problema che non riesco a chiamare una funzione dalla principale nel file .cpp, dichiarata correttamente nel file .h e definita nel file .c. Si è verificato un errore del linker. Nel frattempo posso chiamare la funzione dal solito file .c. Forse dipende dalla convenzione di chiamata. La soluzione era quella di aggiungere le seguenti linee di pre-elaborazione in ogni file .h:

#ifdef __cplusplus
extern "C"
{
#endif

e questi alla fine

#ifdef __cplusplus
}
#endif

7

Ho riscontrato un errore in cui il mio progetto è stato compilato come progetto x64 . e ho usato una libreria compilata come x86 .

Ho ricompilato la libreria come x64 e l'ho risolto.


5

a volte se viene aggiunto un nuovo file di intestazione e questo errore inizia a causa di ciò, è necessario aggiungere anche la libreria per sbarazzarsi di unresolved external symbol.

per esempio:

#include WtsApi32.h

avrà bisogno:

#pragma comment(lib, "Wtsapi32.lib") 

4

Ho avuto gli stessi errori di collegamento, ma da un progetto di test che faceva riferimento a un'altra DLL. Ho scoperto che dopo aver aggiunto _declspec(dllexport)davanti a ciascuna funzione specificata nel messaggio di errore, il collegamento funzionava bene.


3

Credo che la maggior parte dei punti riguardanti le cause e i rimedi siano stati coperti da tutti i partecipanti a questo thread. Voglio solo sottolineare il mio problema "esterno non risolto", è stato causato da un tipo di dati definito come macro che viene sostituito in modo diverso dal previsto, con il risultato che quel tipo errato viene fornito alla funzione in questione e poiché la funzione con tipo non è mai definito, non avrebbe potuto essere risolto. In particolare, in C / C ++ -> Lingua, esiste un attributo chiamato "Tratta WChar_t come tipo incorporato, che avrebbe dovuto essere definito come" No (/ Zc: wchar_t-) "ma non nel mio caso.


grazie, questo causa il problema dal mio setup ('No (/ Zc: wchar_t-)')
Noypi Gilas

2

Oltre all'eccellente risposta di Chris Morris sopra, ho trovato un modo molto interessante che puoi ricevere questo stesso errore se stai chiamando a un metodo virtuale che non è stato impostato su puro ma non ha una sua implementazione. È la stessa identica ragione (il compilatore non riesce a trovare un'implementazione del metodo e quindi i truffatori), ma il mio IDE non ha rilevato questo errore nel minimo bit.

ad esempio, il codice seguente otterrebbe un errore di compilazione con lo stesso messaggio di errore:

//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;
    }
}

Tuttavia, cambiando IamInterface myFunc () in modo che sia un metodo virtuale puro (un metodo che "deve" essere implementato, che rispetto a un metodo virtuale che è un metodo che "può" essere sovrascritto) eliminerà l'errore di compilazione.

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

Spero che questo aiuti la prossima persona StackOverFlow a sfogliare il codice!



2

Assicurati di decorare i tuoi file di intestazione con

#ifndef YOUR_HEADER_H
#define YOUR_HEADER_H

// your header code here

#endif

Se non lo fai, possono succedere cose brutte, incluso questo


8
Che ne dici di usare #pragma once?
Allen Linatoc,

2

Ancora un altro possibile problema (che mi sono appena grattato la testa per qualche tempo):

Se definisci le tue funzioni come inline, ovviamente - devono essere definite nell'intestazione (o in un file inline ), non in un cpp .
Nel mio caso, erano in un file inline, ma solo perché erano un'implementazione specifica della piattaforma e un cpp includeva questo corrispondente file inl ... invece di un'intestazione. Sì, succede.

Ho pensato di lasciare anche questo qui, forse qualcun altro si imbatte nello stesso problema e lo trova qui.


1
Per chiunque abbia annullato il voto: lascia almeno un commento sul perché pensi che la risposta sia sbagliata o non utile. Un voto negativo senza un commento è inutile al massimo.
Johann Studanski,

1

Ho appena avuto difficoltà con questo. Tutto è stato logicamente impostato. Ho dichiarato un costruttore ma non l'ho definito

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

Mi sono quasi sbattuto la testa sulla tastiera quando ho dimenticato qualcosa di così elementare.


1

Sto facendo un po 'di C ++ per la prima volta da molto tempo e ricevo questo errore quando dimentico di aggiungere il prefisso ClassName :: per la definizione della funzione, poiché è un po' univoco per C ++. Quindi ricordati di controllare anche quello!


1

Una possibile causa di questo errore del linker può anche essere le inlinefunzioni dichiarate ma non definite in un file di intestazione che viene poi incluso altrove. Le funzioni incorporate devono essere definite in ogni unità di traduzione in cui sono utilizzate.


0

PUNTATORI

Ho avuto questo problema e l'ho risolto usando il puntatore. Vedo che questo non è stato un tuo problema, ma ho pensato di menzionarlo perché vorrei davvero che fosse stato qui quando l'ho visto un'ora fa. Il mio problema riguardava la dichiarazione di una variabile membro statica senza definirla (la definizione doveva venire dopo alcune altre configurazioni) e ovviamente un puntatore non ha bisogno di una definizione. Altrettanto elementare errore: P


3
Un esempio sarebbe molto utile qui.
moffeltje,

0

Il mio problema era uno sconscript che non conteneva il cppfile definito. Questo può essere molto confuso perché Visual Studio ha il cppfile nel progetto ma qualcos'altro sta costruendo interamente.


0

Il mio problema era: dovevo fare una dichiarazione in avanti della classe il cui direttore era "esterno non risolto".

Nel file in cui ho ricevuto l'errore, ho dovuto inserire qualcosa del genere:

#include "ClassB" 

class ClassB; // this solved the problem

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

Naturalmente, il mio progetto è molto più complicato e questo è solo un esempio di frammento. Anche quando si usano gli spazi dei nomi, dichiararli pure .


0

Ho appena trascorso un paio d'ore per scoprire che il problema era che il mio file principale aveva l'estensione .cinvece di.cpp

:/


0

Ancora un'altra possibilità da verificare, questa volta è stato un mio problema.

Avevo aggiunto la funzione alla libreria e avevo incluso la cartella di output della libreria nel percorso di ricerca.

Ma avevo anche una cartella con una versione precedente della libreria elencata prima, quindi VS stava usando la vecchia libreria e ovviamente non trovava la nuova funzione.


0

Assicurarsi di non tentare di sovraccaricare gli operatori di inserimento o estrazione come funzioni incorporate. Ho avuto questo problema ed è andato via solo quando ho rimosso quella parola chiave.


0

Cosa l'aveva causato nel mio caso:

Ho avuto un file enorme Foo.cppsenza Foo.h. Foo.cppè iniziato così:

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

Ho rimosso la parola chiave "statica" e ho aggiunto un Foo.hcon questo:

extern int var;

Vedi l'errore?

Mi mancava totalmente che var fosse originariamente definito in uno spazio dei nomi, perché la dichiarazione dello spazio dei nomi era sepolta in un altro codice. La soluzione è cambiare l'esterno in questo modo:

namespace NS {
     extern int var;
}

0

Un possibile motivo dell'errore "Simbolo esterno non risolto" può essere la convenzione di chiamata della funzione.

Assicurarsi che tutti i file di origine utilizzino lo stesso standard (.c o .cpp) o specificare la convenzione di chiamata.

Altrimenti, se un file è un file C (source.c) e un altro file è un file .cpp e si collegano alla stessa intestazione, verrà generato l'errore "simbolo esterno non risolto", poiché la funzione viene prima definita come una funzione C cdecl, ma quindi il file C ++ che utilizza la stessa intestazione cercherà una funzione C ++.

Per evitare "Errore di simbolo esterno non risolto", assicurarsi che la convenzione di chiamata della funzione sia mantenuta invariata tra i file che la utilizzano.


0

Sono venuto qui alla ricerca di una possibile spiegazione prima di dare un'occhiata più da vicino alle righe che precedono l'errore del linker. Si è rivelato essere un eseguibile aggiuntivo per il quale mancava la dichiarazione globale!


0

Ho appena avuto lo stesso errore e riesco a evitarlo sostituendolo ;con {}nel file di intestazione.

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

Quando era void xyzMethod();non voleva compilare.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.