Nierozwiązany symbol zewnętrzny w plikach obiektowych

180

Podczas kodowania w Visual Studio otrzymałem nierozwiązany błąd symbolu zewnętrznego i nie mam pojęcia, co robić. Nie wiem co jest źle. Czy mógłbyś mnie rozszyfrować? Gdzie powinienem szukać jakich błędów?

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
źródło
26
Nierozwiązany symbol to taki, który gdzieś zadeklarowałeś, ale którego nigdy nie zdefiniowałeś. Zazwyczaj oznacza to, że # zawarłeś plik nagłówkowy biblioteki innej firmy, ale nie powiedziałeś linkerowi, gdzie znaleźć odpowiednie pliki .obj dla biblioteki.
deong
7
Dość powszechnym błędem jest to, że definiujesz funkcję jako samodzielną i zapominasz selektora klasy w pliku .cpp : Robisz to (źle): void myFunc() { /* do stuff */ } Zamiast tego (dobrze): void A::myFunc() { /* do stuff */ }
jave.web
Można również dodać nawiasy bezpośrednio w nagłówku pliku, jeśli nie chcesz, aby określić go bardziej w pliku .cpp, tak: void myFunc() {};.
Patapoom

Odpowiedzi:

303

Ten błąd często oznacza, że ​​jakaś funkcja ma deklarację, ale nie ma definicji.

Przykład:

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

// A.cpp

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

W twoim przypadku nie można znaleźć definicji. Problemem może być to, że dołączasz plik nagłówka, który zawiera niektóre deklaracje funkcji, ale albo:

  1. nie definiuj funkcji w pliku cpp (jeśli sam napisałeś ten kod)
  2. nie dołączaj pliku lib / dll, który zawiera definicje

Częstym błędem jest to, że definiujesz funkcję jako samodzielną i zapominasz selektora klasy, np. A::W pliku .cpp :

Źle: void myFunc() { /* do stuff */ }
Racja: void A::myFunc() { /* do stuff */ }

Chris Morris
źródło
2
Jak dołączyć wspomniany plik lib do mojego projektu?
tmj
@tMJ Zależy to od używanego środowiska. Poszukałbym samouczków online lub na tej stronie.
Chris Morris
@ChrisMorris Definicja funkcji nie była dostępna, ponieważ nie powiązałem jej poprawnie lub coś w tym rodzaju. Ale ponieważ dll nie był w pamięci i musiał zostać załadowany za pomocą wywołania LoadLibrary. (FTR)
tmj
2
Ostatnia rada była właśnie problemem. Robiłem void myFunc() {}zamiast A::void myFunc() {}.
Charles
Genialna odpowiedź. Właściwie zapomniałem zarówno (1), jak i części A :: po skopiowaniu metody z innego miejsca.
RoG
24

Sprawdź, czy dołączasz wszystkie pliki źródłowe do swojego rozwiązania, do którego się odwołujesz.

Jeśli nie dołączasz pliku źródłowego (a więc i implementacji) dla klasy Fieldw swoim projekcie, nie zostanie on zbudowany i nie będziesz mógł utworzyć łącza podczas kompilacji.

Alternatywnie, być może używasz biblioteki statycznej lub dynamicznej i zapomniałeś powiedzieć linkerowi o .libs?

Konrad
źródło
3
Odwołanie do prawidłowych plików lib rozwiązało problem. Użyj Project-> Właściwości-> Linker-> Ogólne-> Dodatkowe katalogi biblioteczne i Projekt-> Właściwości-> Linker-> Wejście-> Dodatkowe zależności, aby odnieść się do katalogu lib i plików lib
zak
11

Wygląda na to, że brakuje biblioteki lub dołączenia, możesz spróbować dowiedzieć się, która klasa biblioteki ma getName, getType itp. ... i umieść to w pliku nagłówkowym lub za pomocą #include.

Również jeśli są one z zewnętrznej biblioteki, upewnij się, że odwołujesz się do nich w pliku projektu. Na przykład, jeśli ta klasa należy do abc.lib, to w Visual Studio

  1. Kliknij Właściwości projektu.
  2. Idź do Właściwości konfiguracji, C / C ++, Generuj, sprawdź, czy wskazujesz lokalizację abc.lib w Dodatkowych katalogach dołączania. W Linker, Input, upewnij się, że masz abc.lib w części Dodatkowe zależności.
Fylix
źródło
9

Właśnie widziałem problem, że nie mogę wywołać funkcji z głównego w pliku .cpp, poprawnie zadeklarowanego w pliku .h i zdefiniowanego w pliku .c. Wystąpił błąd linkera. Tymczasem mogę wywołać funkcję ze zwykłego pliku .c. Być może zależy to od konwencji połączeń. Rozwiązaniem było dodanie następujących wierszy preproc w każdym pliku .h:

#ifdef __cplusplus
extern "C"
{
#endif

i te w końcu

#ifdef __cplusplus
}
#endif
Alexey257
źródło
7

Wystąpił błąd, gdy mój projekt został skompilowany jako projekt x64 . i użyłem biblioteki skompilowanej jako x86 .

Skompilowałem bibliotekę jako x64 i to rozwiązało.

Gal Bracha
źródło
5

czasami, jeśli dodawany jest nowy plik nagłówka, a ten błąd zaczyna się pojawiać z tego powodu, musisz również dodać bibliotekę, aby się go pozbyć unresolved external symbol.

na przykład:

#include WtsApi32.h

będzie potrzebował:

#pragma comment(lib, "Wtsapi32.lib") 
Shashank
źródło
4

Miałem te same błędy łącza, ale z projektu testowego, który odwoływał się do innej biblioteki DLL. Okazało się, że po dodaniu _declspec(dllexport)przed każdą funkcją określoną w komunikacie o błędzie łącze działało dobrze.

meJustAndrew
źródło
3

Wierzę, że większość punktów dotyczących przyczyn i środków zaradczych została omówiona przez wszystkich autorów tego wątku. Chciałbym tylko zwrócić uwagę na mój „nierozwiązany problem zewnętrzny”, spowodowany przez typ danych zdefiniowany jako makro, który jest podstawiany inaczej niż oczekiwano, co powoduje, że do tej funkcji jest dostarczany ten niepoprawny typ i ponieważ funkcja z typem nigdy nie jest zdefiniowany, nie można go rozwiązać. W szczególności pod C / C ++ -> Language istnieje atrybut o nazwie „Treat WChar_t As Built in Type, który powinien był zostać zdefiniowany jako„ No (/ Zc: wchar_t-) ”, ale w moim przypadku tak nie było.

Patrick Nguyen
źródło
dzięki, to powoduje problem z moją konfiguracją („No (/ Zc: wchar_t-)”)
Noypi Gilas
2

Oprócz doskonałej odpowiedzi Chrisa Morrisa powyżej, znalazłem bardzo ciekawy sposób, aby otrzymać tę samą usterkę, jeśli wywołujesz metodę wirtualną, która nie została ustawiona na czystą, ale nie ma własnej implementacji. Jest to dokładnie ten sam powód (kompilator nie może znaleźć implementacji metody, a zatem oszustów), ale moje IDE nie złapało tego błędu w najmniejszym stopniu.

na przykład następujący kod otrzyma błąd kompilacji z tym samym komunikatem o błędzie:

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

Jednak zmiana IamInterface myFunc () na czystą metodę wirtualną (metodę, którą trzeba zaimplementować, że zamiast metody wirtualnej, która jest metodą, którą można zastąpić) można wyeliminować błąd kompilacji.

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

Ma nadzieję, że pomoże to następnej osobie StackOverFlow przejść przez kod!

GMLewisII
źródło
2

Patrz Linker Tools Error LNK2019 w MSDN, ma szczegółową listę typowych problemów, które powodują LNK2019.

Alessandro Jacopson
źródło
2

Pamiętaj, aby udekorować pliki nagłówkowe

#ifndef YOUR_HEADER_H
#define YOUR_HEADER_H

// your header code here

#endif

Złe rzeczy - w tym to - mogą się zdarzyć, jeśli tego nie zrobisz

Panouden
źródło
8
Co powiesz na używanie #pragma once?
Allen Linatoc,
2

Kolejny możliwy problem (po którym drapałem się po głowie):

Jeśli zdefiniujesz swoje funkcje jako inline, będą one - oczywiście! - musiały zostać zdefiniowane w nagłówku (lub pliku wbudowanym ), a nie w cpp .
W moim przypadku były one zawarte w pliku wbudowanym, ale tylko dlatego, że były implementacją specyficzną dla platformy, a procesor cpp zawierał ten odpowiedni plik inl … zamiast nagłówka. Tak, kurwa się dzieje.

Myślałem, że zostawię to tutaj, może ktoś inny napotka ten sam problem i znajdzie go tutaj.

Johann Studański
źródło
1
Do kogo to ocenił: zostaw przynajmniej komentarz, dlaczego uważasz, że odpowiedź jest błędna lub nie jest pomocna. Opinia negatywna bez komentarza jest co najwyżej bezwartościowa.
Johann Studanski
1

Po prostu miałem z tym trudności. Wszystko było logicznie skonfigurowane. Zadeklarowałem konstruktora, ale go nie zdefiniowałem

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

Prawie uderzyłem głową w klawiaturę, gdy zapomniałem czegoś tak podstawowego.

Joe Plante
źródło
1

Robię trochę C ++ po raz pierwszy od dłuższego czasu i pojawia się ten błąd, gdy zapominam dodać przedrostek ClassName :: do definicji funkcji, ponieważ jest to trochę unikalne dla C ++. Pamiętaj więc, aby to sprawdzić!

Matthew Hayes
źródło
1

Jedną z możliwych przyczyn tego błędu linkera mogą być również inlinefunkcje, które są zadeklarowane, ale nie zdefiniowane w pliku nagłówkowym, który jest następnie zawarty w innym miejscu. Funkcje wbudowane muszą być zdefiniowane w każdej jednostce tłumaczeniowej, w której są używane.

bweber
źródło
0

WSKAŹNIKI

Miałem ten problem i rozwiązałem go za pomocą wskaźnika. Widzę, że to nie był twój problem, ale pomyślałem, że wspomnę o tym, ponieważ z pewnością chciałbym, żeby był tutaj, kiedy zobaczyłem to godzinę temu. Mój problem polegał na zadeklarowaniu statycznej zmiennej składowej bez jej definiowania (definicja musiała przyjść po kilku innych ustawieniach) i oczywiście wskaźnik nie potrzebuje definicji. Równie podstawowy błąd: P

Rabel
źródło
3
Przykład byłby bardzo przydatny tutaj.
moffeltje 13.04.16
0

Mój problem polegał na tym, że skrypt nie miał cppzdefiniowanego pliku. Może to być bardzo mylące, ponieważ Visual Studio ma cppplik w projekcie, ale buduje się coś jeszcze.

ubershmekel
źródło
0

Mój problem brzmiał: musiałem złożyć deklarację klasy, której ctor był „nierozwiązany zewnętrznie”.

W pliku, w którym wystąpił błąd, musiałem umieścić coś takiego:

#include "ClassB" 

class ClassB; // this solved the problem

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

Oczywiście mój projekt jest znacznie bardziej skomplikowany, a to tylko krótki fragment. Deklaruj je również podczas korzystania z przestrzeni nazw .

Vicrucann
źródło
0

Spędziłem tylko kilka godzin, aby stwierdzić, że problem polega na tym, że mój główny plik ma rozszerzenie .czamiast.cpp

:/

Madhur
źródło
0

Jeszcze jedna możliwość sprawdzenia, tym razem to mój problem.

Dodałem tę funkcję do biblioteki i umieściłem folder wyjściowy biblioteki w ścieżce wyszukiwania.

Ale miałem też folder ze starszą wersją biblioteki wymienioną wcześniej, więc VS korzystał ze starej biblioteki i oczywiście nie znajdował nowej funkcji.

Francesco Dondi
źródło
0

Upewnij się, że nie próbujesz przeciążać operatorów wstawiania lub wyciągania jako funkcji wbudowanych. Miałem ten problem i zniknął dopiero po usunięciu tego słowa kluczowego.

Skinienie
źródło
0

Co spowodowało to w moim przypadku:

Miałem ogromny plik Foo.cppbez pliku Foo.h. Foo.cppzaczęło się tak:

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

Usunąłem słowo kluczowe „static” i dodałem Foo.hz tym:

extern int var;

Czy widzisz błąd?

Całkowicie mi brakowało, że var został pierwotnie zdefiniowany w przestrzeni nazw, ponieważ deklaracja przestrzeni nazw została pochowana w innym kodzie. Rozwiązaniem jest zmiana zewnętrznego wyglądu w następujący sposób:

namespace NS {
     extern int var;
}
Stefan Monov
źródło
0

Możliwą przyczyną błędu „Nierozwiązany symbol zewnętrzny” może być konwencja wywoływania funkcji.

Upewnij się, że wszystkie pliki źródłowe korzystają z tego samego standardu (.c lub .cpp), lub określ konwencję wywoływania.

W przeciwnym razie, jeśli jeden plik jest plikiem C (source.c), a inny plik jest plikiem .cpp i łączą się z tym samym nagłówkiem, zostanie zgłoszony błąd „nierozwiązany symbol zewnętrzny”, ponieważ funkcja jest najpierw zdefiniowana jako funkcja C cdecl, ale plik C ++ korzystający z tego samego nagłówka będzie szukał funkcji C ++.

Aby uniknąć „nierozwiązanego błędu symbolu zewnętrznego”, upewnij się, że konwencja wywoływania funkcji jest taka sama wśród plików, które z niej korzystają.

Flavio
źródło
0

Przybyłem tutaj, szukając możliwego wyjaśnienia, zanim przyjrzałem się wierszom poprzedzającym błąd linkera. Okazało się, że był to dodatkowy plik wykonywalny, dla którego brakowało globalnej deklaracji!

Jerry Miller
źródło
0

Właśnie miałem ten sam błąd i udało mi się go uniknąć, zastępując ;go {}w pliku nagłówkowym.

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

Kiedy było void xyzMethod();, nie chciał się kompilować.

Lisedra
źródło