Неразрешенный внешний символ в объектных файлах


180

Во время кодирования в Visual Studio я получил неразрешенную внешнюю ошибку символа и понятия не имею, что делать. Я не знаю что не так. Не могли бы вы расшифровать меня? Где я должен искать какие ошибки?

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
Неразрешенный символ - это тот, который вы где-то объявили, но никогда не определяли. Обычно это означает, что вы # включили заголовочный файл сторонней библиотеки, но не сказали компоновщику, где найти соответствующие файлы .obj для библиотеки.
Deong

7
Довольно распространенная ошибка заключается в том, что вы определяете функцию как отдельную и забываете селектор класса в своем файле .cpp : вы делаете это (неправильно): void myFunc() { /* do stuff */ } вместо этого (правильно): void A::myFunc() { /* do stuff */ }
jave.web

Вы также можете добавить скобки непосредственно в заголовке файла , если вы не хотите , чтобы определить его больше в файле .cpp, как это: void myFunc() {};.
Patapoom

Ответы:


303

Эта ошибка часто означает, что у некоторой функции есть объявление, но нет определения.

Пример:

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

// A.cpp

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

В вашем случае определение не может быть найдено. Проблема может заключаться в том, что вы включаете заголовочный файл, который содержит некоторые объявления функций, но вы также:

  1. не определяйте функции в вашем файле cpp (если вы написали этот код самостоятельно)
  2. не включайте файл lib / dll, который содержит определения

Распространенной ошибкой является то, что вы определяете функцию как отдельную и забываете селектор класса, например A::, в вашем файле .cpp :

Неверно: void myFunc() { /* do stuff */ }
верно: void A::myFunc() { /* do stuff */ }


2
Как включить указанный файл lib в мой проект?
tmj

@ tMJ Это зависит от того, какую среду вы используете. Я бы посмотрел учебники онлайн или на этом сайте.
Крис Моррис

@ChrisMorris Определение функции было недоступно не потому, что я не связал ее должным образом или что-то в этом роде. Но, поскольку DLL не было в памяти и должно было быть загружено через вызов LoadLibrary. (FTR)
tmj

2
Последний совет был именно проблемой здесь. Я делал void myFunc() {}вместо A::void myFunc() {}.
Чарльз

Блестящий ответ. Я на самом деле забыл оба (1) и затем A :: часть после копирования метода из другого места.
RoG

24

Убедитесь, что вы включаете в исходное решение все исходные файлы, на которые ссылаетесь.

Если вы не включите исходный файл (и, следовательно, реализацию) для класса Fieldв ваш проект, он не будет собран, и вы не сможете связать во время компиляции.

В качестве альтернативы, возможно, вы используете статическую или динамическую библиотеку и забыли рассказать компоновщику о .libs?


3
Ссылка на правильные файлы lib решила проблему. Используйте Project-> Properties-> Linker-> General-> Дополнительные каталоги библиотек и Project-> Properties-> Linker-> Input-> Дополнительные зависимости, чтобы ссылаться на каталог lib и файлы lib
zak

11

Похоже, что отсутствует библиотека или включить, вы можете попытаться выяснить, какой класс вашей библиотеки имеют getName, getType и т. Д ... и поместить это в файл заголовка или использование #include.

Также, если это происходит из внешней библиотеки, убедитесь, что вы ссылаетесь на них в файле проекта. Например, если этот класс принадлежит abc.lib, то в вашей Visual Studio

  1. Нажмите на Свойства проекта.
  2. Перейдите в Свойства конфигурации, C / C ++, Создать, убедитесь, что вы указываете на местоположение abc.lib в разделе Дополнительные каталоги включения. Под Linker, Input, убедитесь, что у вас есть abc.lib в разделе Дополнительные зависимости.

9

Я только что видел проблему, я не могу вызвать функцию из main в файле .cpp, правильно объявлена ​​в файле .h и определена в файле .c. Обнаружена ошибка компоновщика. Пока что я могу вызвать функцию из обычного .c файла. Возможно, это зависит от соглашения о вызовах. Решением было добавить следующие строки preproc в каждый файл .h:

#ifdef __cplusplus
extern "C"
{
#endif

и это в конце

#ifdef __cplusplus
}
#endif

7

У меня была ошибка, когда мой проект был скомпилирован как проект x64 . и я использовал библиотеку, которая была скомпилирована как x86 .

Я перекомпилировал библиотеку как x64, и она решила это.


5

иногда, если добавляется новый заголовочный файл, и эта ошибка начинает появляться из-за этого, вам также необходимо добавить библиотеку, чтобы избавиться от нее unresolved external symbol.

например:

#include WtsApi32.h

будет нужно:

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

4

У меня были те же ошибки ссылки, но из тестового проекта, который ссылался на другую DLL. Выяснилось, что после добавления _declspec(dllexport)перед каждой функцией, указанной в сообщении об ошибке, ссылка работала хорошо.


3

Я полагаю, что большинство участников этой темы рассмотрели большинство вопросов, касающихся причин и способов устранения неполадок. Я просто хочу указать на мою «неразрешенную внешнюю» проблему, это было вызвано типом данных, определенным как макрос, который подставляется не так, как ожидалось, что приводит к тому, что неправильный тип передается в рассматриваемую функцию, и так как функция с типом никогда не определяется, это не могло быть решено. В частности, в C / C ++ -> Language есть атрибут под названием «Обработать WChar_t как встроенный тип», который должен был быть определен как «Нет (/ Zc: wchar_t-)», но в моем случае этого не произошло.


спасибо, это вызывает проблему из моей установки ('Нет (/ Zc: wchar_t-)')
Нойпи Гилас

2

В дополнение к превосходному ответу Криса Морриса, приведенному выше, я обнаружил очень интересный способ получения этой же ошибки, если вы вызываете виртуальный метод, который не был установлен в чистый, но не имеет собственной реализации. Это та же самая причина (компилятор не может найти реализацию метода и, следовательно, мошенников), но моя IDE не уловила эту ошибку ни в малейшей степени.

например, следующий код получит ошибку компиляции с тем же сообщением об ошибке:

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

Однако изменение IamInterface myFunc () на чистый виртуальный метод (метод, который должен быть реализован, а не виртуальный метод, который является методом, который может быть переопределен), устранит ошибку компиляции.

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

Надеется, что это поможет следующему человеку StackOverFlow пройти через код!



2

Убедитесь, что вы украсили свои заголовочные файлы

#ifndef YOUR_HEADER_H
#define YOUR_HEADER_H

// your header code here

#endif

Плохие вещи, включая это, могут случиться, если вы этого не сделаете


8
Как насчет использования #pragma once?
Аллен Линаток

2

Еще одна возможная проблема (о которой я просто почесал голову в течение некоторого времени):

Если вы определяете свои функции как inline, они - конечно! - должны быть определены в заголовке (или встроенном файле), а не в cpp .
В моем случае они были во встроенном файле, но только потому, что они были реализацией для конкретной платформы, и cpp включил этот соответствующий файл inl ... вместо заголовка. Да, это так.

Я тоже решил оставить это здесь, может быть, кто-то столкнется с той же проблемой и найдет ее здесь.


1
Кому бы это не понравилось: оставьте хотя бы комментарий, почему вы считаете ответ неправильным или бесполезным. Понижение без комментариев бесполезно в лучшем случае.
Иоганн Студански

1

Мне просто было тяжело с этим. Все было логично настроено. Я объявил конструктор, но не определил его

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

Я чуть не ударился головой о клавиатуру, когда забыл что-то такое элементарное.


1

Я делаю немного C ++ впервые за долгое время, и я получаю эту ошибку, когда забываю добавить префикс ClassName :: для определения функции, так как это немного уникально для C ++. Так что не забудьте проверить это тоже!


1

Одной из возможных причин этой ошибки компоновщика также могут быть inlineфункции, которые объявлены, но не определены в заголовочном файле, который затем включается в другое место. Встроенные функции должны быть определены в каждой единице перевода, в которой они используются.


0

УКАЗАТЕЛИ

Я имел эту проблему и решил ее с помощью указателя. Я вижу, что это не твоя проблема, но я подумал упомянуть об этом, потому что, конечно, хотел бы, чтобы это было здесь, когда я увидел это час назад. Моя проблема была в том, чтобы объявить статическую переменную-член без ее определения (определение должно было прийти после некоторых других настроек), и, конечно, указатель не нуждается в определении. Столь же элементарная ошибка: P


3
Пример был бы очень полезен здесь.
Моффельте

0

Моя проблема была в сценарии, в котором не было cppопределено файла. Это может быть очень запутанным, потому что Visual Studio имеет cppфайл в проекте, но что-то еще полностью строит.


0

Моя проблема заключалась в следующем: я должен был сделать предварительное объявление класса, чей cort был «неразрешенным внешним».

В файл, где я получил ошибку, я должен был поместить что-то вроде этого:

#include "ClassB" 

class ClassB; // this solved the problem

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

Конечно, мой проект намного сложнее, и это всего лишь пример фрагмента. Также при использовании пространств имен объявляйте их .


0

Просто потратил пару часов, чтобы выяснить, что проблема заключалась в том, что мой основной файл имел расширение .cвместо.cpp

:/


0

Еще одна возможность проверить, на этот раз это была моя проблема.

Я добавил функцию в библиотеку и включил выходную папку библиотеки в путь поиска.

Но у меня также была папка со старой версией библиотеки, перечисленной ранее, поэтому VS использовал старую библиотеку и, конечно, не нашел новую функцию.


0

Убедитесь, что вы не пытаетесь перегрузить операторы вставки или извлечения как встроенные функции. У меня была эта проблема, и она исчезла только тогда, когда я удалил это ключевое слово.


0

Что вызвало это в моем случае:

У меня был огромный файл Foo.cppбез Foo.h. Foo.cppначалось так:

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

Я удалил ключевое слово "static" и добавил Foo.hс этим:

extern int var;

Вы видите ошибку?

Я полностью упустил тот факт, что var изначально определялся в пространстве имен, потому что объявление пространства имен было похоронено в другом коде. Исправление должно изменить внешний вид как это:

namespace NS {
     extern int var;
}

0

Возможной причиной ошибки «Неразрешенный внешний символ» может быть соглашение о вызове функции.

Убедитесь, что все исходные файлы используют один и тот же стандарт (.c или .cpp), или укажите соглашение о вызовах.

В противном случае, если один файл является файлом C (source.c), а другой файл - файлом .cpp, и они ссылаются на один и тот же заголовок, то будет выдана ошибка «неразрешенный внешний символ», поскольку функция сначала определяется как функция C cdecl, но затем файл C ++, использующий тот же заголовок, будет искать функцию C ++.

Чтобы избежать «Неразрешенной ошибки внешнего символа», убедитесь, что соглашение о вызовах функций остается неизменным среди файлов, использующих его.


0

Я пришел сюда в поисках возможного объяснения, прежде чем присмотреться к строкам, предшествующим ошибке компоновщика. Оказалось, что это был дополнительный исполняемый файл, для которого отсутствовало глобальное объявление!


0

Я только имел ту же ошибку , и мне удается избежать путем замены ;с {}в файле заголовка.

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

Когда это было, void xyzMethod();он не хотел компилировать.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.