Símbolo externo no resuelto en archivos de objetos

180

Durante la codificación en Visual Studio recibí un error de símbolo externo no resuelto y no tengo idea de qué hacer. No se lo que está mal. ¿Podría por favor descifrarme? ¿Dónde debería estar buscando qué tipo de errores?

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
fuente
26
Un símbolo no resuelto es uno que ha declarado en algún lugar pero nunca ha definido. Por lo general, significa que ha #incluido el archivo de encabezado de una biblioteca de terceros pero no le ha dicho al vinculador dónde encontrar los archivos .obj correspondientes para la biblioteca.
deong
77
Un error bastante común es que define una función como independiente y olvida el selector de clase en su archivo .cpp : hace esto (incorrecto): en void myFunc() { /* do stuff */ } lugar de esto (correcto): void A::myFunc() { /* do stuff */ }
jave.web
También se pueden añadir soportes directamente en su cabecera de archivo si no desea definir más en su archivo .cpp, así: void myFunc() {};.
Patapoom

Respuestas:

303

Este error a menudo significa que alguna función tiene una declaración, pero no una definición.

Ejemplo:

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

// A.cpp

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

En su caso, no se puede encontrar la definición. El problema podría ser que está incluyendo un archivo de encabezado, que trae algunas declaraciones de funciones, pero usted:

  1. no defina las funciones en su archivo cpp (si usted mismo escribió este código)
  2. no incluya el archivo lib / dll que contiene las definiciones

Un error común es que define una función como independiente y olvida el selector de clase, por ejemplo A::, en su .cpp archivo :

Incorrecto: void myFunc() { /* do stuff */ }
Correcto: void A::myFunc() { /* do stuff */ }

Chris Morris
fuente
2
¿Cómo incluir dicho archivo lib en mi proyecto?
tmj
@tMJ Depende del entorno que esté utilizando. Buscaría tutoriales en línea o en este sitio.
Chris Morris
@ChrisMorris La definición de la función no estaba disponible no porque no la vinculé correctamente o algo así. Pero, porque el dll no estaba en la memoria y tenía que cargarse a través de una llamada LoadLibrary. (FTR)
tmj
2
El último consejo fue exactamente el problema aquí. Estaba haciendo en void myFunc() {}lugar de A::void myFunc() {}.
Charles
Brillante respuesta. En realidad, había olvidado tanto (1) como la parte A :: después de copiar el método desde otro lugar.
RoG
24

Compruebe que incluye todos los archivos de origen dentro de su solución a la que hace referencia.

Si no incluye el archivo fuente (y, por lo tanto, la implementación) para la clase Field en su proyecto, no se generará y no podrá vincularlo durante la compilación.

Alternativamente, ¿tal vez está utilizando una biblioteca estática o dinámica y ha olvidado decirle al vinculador sobre el .libs?

Konrad
fuente
3
Referir los archivos lib correctos resolvió el problema. Use Proyecto-> Propiedades-> Enlazador-> General-> Directorios de biblioteca adicionales y Proyecto-> Propiedades-> Enlazador-> Entrada-> Dependencias adicionales para consultar el directorio lib y los archivos lib
zak
11

Parece que falta una biblioteca o incluye, puede intentar averiguar qué clase de su biblioteca tiene getName, getType, etc. y ponerla en el archivo de encabezado o usarla #include.

Además, si estos provienen de una biblioteca externa, asegúrese de hacer referencia a ellos en su archivo de proyecto. Por ejemplo, si esta clase pertenece a un abc.lib, entonces en su Visual Studio

  1. Haga clic en Propiedades del proyecto.
  2. Vaya a Propiedades de configuración, C / C ++, Generar, verifique que apunte a la ubicación abc.lib en Directorios de inclusión adicionales. En Linker, Input, asegúrese de tener abc.lib en Dependencias adicionales.
Fylix
fuente
9

Acabo de ver el problema. No puedo llamar a una función desde main en el archivo .cpp, declarada correctamente en el archivo .h y definida en el archivo .c. Encontró un error de vinculador. Mientras tanto, puedo llamar a la función desde el archivo .c habitual. Posiblemente depende de la convención de llamadas. La solución fue agregar las siguientes líneas de preproceso en cada archivo .h:

#ifdef __cplusplus
extern "C"
{
#endif

y estos al final

#ifdef __cplusplus
}
#endif
Alexey257
fuente
7

Tuve un error en el que mi proyecto se compiló como proyecto x64 . y he usado una biblioteca que fue compilada como x86 .

He compilado la biblioteca como x64 y la resolvió.

Gal Bracha
fuente
5

a veces, si se agrega un nuevo archivo de encabezado, y este error comienza a aparecer debido a eso, también debe agregar la biblioteca para deshacerse de unresolved external symbol .

por ejemplo:

#include WtsApi32.h

necesitará:

#pragma comment(lib, "Wtsapi32.lib") 
Shashank
fuente
4

Tuve los mismos errores de enlace, pero de un proyecto de prueba que hacía referencia a otro dll. Descubrí que después de agregar _declspec(dllexport)delante de cada función que se especificó en el mensaje de error, el enlace funcionaba bien.

yo soloAndrew
fuente
3

Creo que la mayoría de los contribuyentes en este hilo han cubierto la mayoría de los puntos relacionados con las causas y los remedios. Solo quiero señalar mi problema 'externo no resuelto', fue causado por un tipo de datos definido como macro que se sustituye de manera diferente a la esperada, lo que resulta en que se suministre ese tipo incorrecto a la función en cuestión, y dado que la función con tipo nunca se define, no se pudo haber resuelto. En particular, en C / C ++ -> Language, hay un atributo llamado 'Tratar WChar_t como tipo incorporado, que debería haberse definido como' No (/ Zc: wchar_t-) 'pero no en mi caso.

Patrick Nguyen
fuente
gracias, esto causa el problema de mi configuración ('No (/ Zc: wchar_t-)')
Noypi Gilas
2

Además de la excelente respuesta de Chris Morris anterior, encontré una forma muy interesante de recibir esta misma falla si está llamando a un método virtual que no se ha configurado como puro pero que no tiene su propia implementación. Es exactamente la misma razón (el compilador no puede encontrar una implementación del método y, por lo tanto, estafadores), pero mi IDE no detectó esta falla en lo más mínimo.

por ejemplo, el siguiente código obtendría un error de compilación con el mismo mensaje de error:

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

Sin embargo, cambiar IamInterface myFunc () para que sea un método virtual puro (un método que "debe" implementarse, que un método virtual que es un método que puede "anularse") eliminará el error de compilación.

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

¡Espera que esto ayude a la próxima persona de StackOverFlow a pasar por el código!

GMLewisII
fuente
2

Asegúrese de decorar sus archivos de encabezado con

#ifndef YOUR_HEADER_H
#define YOUR_HEADER_H

// your header code here

#endif

Cosas malas, incluido esto, pueden suceder si no

Panouden
fuente
8
¿Qué tal el uso #pragma once?
Allen Linatoc
2

Otro posible problema (que me rasqué la cabeza por algún tiempo):

Si define sus funciones como inline, por supuesto, deben definirse en el encabezado (o en un archivo en línea ), no en un cpp .
En mi caso, estaban en un archivo en línea, pero solo porque eran una implementación específica de la plataforma, y ​​un cpp incluía este archivo inl correspondiente ... en lugar de un encabezado. Sí, mierda pasa.

Pensé que también dejaría esto aquí, tal vez alguien más se encuentre con el mismo problema y lo encuentre aquí.

Johann Studanski
fuente
1
A quien haya votado en contra de esto: deje al menos un comentario por qué cree que la respuesta es incorrecta o no es útil. Un voto negativo sin un comentario es inútil en el mejor de los casos.
Johann Studanski
1

Acabo de pasar un mal momento con esto. Todo estaba lógicamente configurado. Declaré un constructor pero no lo definí

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

Casi me golpeo la cabeza con el teclado cuando olvidé algo tan elemental.

Joe Plante
fuente
1

Estoy haciendo algo de C ++ por primera vez en mucho tiempo, y obtengo este error cuando olvido agregar el prefijo ClassName :: para la definición de la función, ya que esto es un poco exclusivo de C ++. ¡Así que recuerda comprobar eso también!

Matthew Hayes
fuente
1

Una posible causa de este error del enlazador también puede ser inlinefunciones que se declaran pero no se definen en un archivo de encabezado que luego se incluye en otro lugar. Las funciones en línea deben definirse en cada unidad de traducción en la que se utilizan.

Bweber
fuente
0

Punteros

Tuve este problema y lo resolví usando el puntero. Veo que este no fue tu problema, pero pensé en mencionarlo porque desearía que hubiera estado aquí cuando lo vi hace una hora. Mi problema era declarar una variable miembro estática sin definirla (la definición debía venir después de algunas otras configuraciones) y, por supuesto, un puntero no necesita una definición. Error igualmente elemental: P

Rabel
fuente
3
Un ejemplo sería muy útil aquí.
moffeltje
0

Mi problema fue que un sconscript no tenía el cpparchivo definido en él. Esto puede ser muy confuso porque Visual Studio tiene el cpparchivo en el proyecto pero se está construyendo algo completamente diferente.

ubershmekel
fuente
0

Mi problema era: tenía que hacer una declaración de la clase cuyo ctor era "externo sin resolver".

En el archivo donde obtuve el error, tuve que poner algo como esto:

#include "ClassB" 

class ClassB; // this solved the problem

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

Por supuesto, mi proyecto es mucho más complicado y este es solo un ejemplo de fragmento. También cuando use espacios de nombres, declare también .

vicrucann
fuente
0

Solo pasé un par de horas para descubrir que el problema era que mi archivo principal tenía extensión en .clugar de.cpp

:/

Madhur
fuente
0

Otra posibilidad más para verificar, esta vez fue mi problema.

Agregué la función a la biblioteca e incluí la carpeta de salida de la biblioteca en la ruta de búsqueda.

Pero también tenía una carpeta con una versión anterior de la biblioteca mencionada anteriormente, por lo que VS estaba usando la biblioteca anterior y, por supuesto, no encontraba la nueva función.

Francesco Dondi
fuente
0

Asegúrese de no intentar sobrecargar los operadores de inserción o extracción como funciones en línea. Tuve este problema y solo desapareció cuando eliminé esa palabra clave.

Arroyo
fuente
0

Lo que lo causó en mi caso:

Tenía un archivo enorme Foo.cppsin un Foo.h. Foo.cppcomenzó así:

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

Eliminé la palabra clave "estática" y agregué una Foo.hcon esto:

extern int var;

¿Ves el error?

Extrañé totalmente que var se definiera originalmente en un espacio de nombres, porque la declaración del espacio de nombres estaba enterrada en otro código. La solución es cambiar el externo de esta manera:

namespace NS {
     extern int var;
}
Stefan Monov
fuente
0

Una posible razón para el error "Símbolo externo no resuelto" puede ser la convención de llamada de función.

Asegúrese de que todos los archivos de origen estén usando el mismo estándar (.c o .cpp), o especifique la convención de llamada.

De lo contrario, si un archivo es un archivo C (source.c) y otro archivo es un archivo .cpp, y se vinculan al mismo encabezado, se generará el error "símbolo externo no resuelto", porque la función se define primero como una función C cdecl, pero luego el archivo C ++ que usa el mismo encabezado buscará una función C ++.

Para evitar el "error de símbolo externo no resuelto", asegúrese de que la convención de llamada de función se mantenga igual entre los archivos que la utilizan.

Flavio
fuente
0

Vine aquí buscando una posible explicación antes de echar un vistazo más de cerca a las líneas que preceden al error del enlazador. ¡Resultó haber sido un ejecutable adicional para el que faltaba la declaración global!

Jerry Miller
fuente
0

Acabo de tener el mismo error y me las arreglo para evitarlo mediante la sustitución ;con {}en el archivo de cabecera.

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

Cuando era void xyzMethod();no quería compilar.

Lisedra
fuente