Símbolo externo no resuelto en miembros de clase estática

129

En pocas palabras:

Tengo una clase que consta principalmente de miembros públicos estáticos, por lo que puedo agrupar funciones similares que aún deben llamarse desde otras clases / funciones.

De todos modos, he definido dos variables char sin signo estáticas en el ámbito público de mi clase, cuando intento modificar estos valores en el constructor de la misma clase, obtengo un error de "símbolo externo no resuelto" en la compilación.

class test 
{
public:
    static unsigned char X;
    static unsigned char Y;

    ...

    test();
};

test::test() 
{
    X = 1;
    Y = 2;
}

Soy nuevo en C ++, así que ve con calma. ¿Por qué no puedo hacer esto?

AustinWBryan
fuente

Respuestas:

145

Olvidó agregar las definiciones para que coincidan con sus declaraciones de X e Y

unsigned char test::X;
unsigned char test::Y;

algun lado. Es posible que también desee inicializar un miembro estático

unsigned char test::X = 4;

y nuevamente, lo hace en la definición (generalmente en un archivo CXX) no en la declaración (que a menudo está en un archivo .H)

Colin Jensen
fuente
44
Si está escribiendo una biblioteca de solo encabezado, puede usar esta técnica para evitar el archivo cpp: stackoverflow.com/questions/11709859/…
Shital Shah
62

Las declaraciones de miembros de datos estáticos en la declaración de clase no son una definición de ellas. Para definirlos, debe hacer esto en el .CPParchivo para evitar símbolos duplicados.

Los únicos datos que puede declarar y definir son constantes estáticas integrales. (Los valores de enumspueden usarse también como valores constantes)

Es posible que desee volver a escribir su código como:

class test {
public:
  const static unsigned char X = 1;
  const static unsigned char Y = 2;
  ...
  test();
};

test::test() {
}

Si desea tener la capacidad de modificar sus variables estáticas (en otras palabras, cuando no es apropiado declararlas como constantes), puede separar su código entre .Hy .CPPde la siguiente manera:

.H:

class test {
public:

  static unsigned char X;
  static unsigned char Y;

  ...

  test();
};

.CPP:

unsigned char test::X = 1;
unsigned char test::Y = 2;

test::test()
{
  // constructor is empty.
  // We don't initialize static data member here, 
  // because static data initialization will happen on every constructor call.
}
sergtk
fuente
¿Por qué aquí en .CPP, es "unsigned char test :: X = 1;" en lugar de "test :: X = 1;"? variable estática X ya definida, ¿por qué todavía necesita "char sin firmar"? @sergtk
Penny
@ Penny Porque "test :: X = 1;" se interpreta como una tarea, mientras que lo que estamos tratando de hacer es una definición.
Anónimo1847
4

Dado que este es el primer hilo SO que parece surgir cuando busco "elementos externos no resueltos con miembros constantes estáticos" en general, dejaré aquí otra pista para resolver un problema con elementos externos no resueltos aquí:

Para mí, lo que olvidé fue marcar la definición de mi clase __declspec(dllexport), y cuando llamé desde otra clase (fuera de los límites de dll de esa clase), por supuesto, recibí el error externo no resuelto.
Aún así, es fácil de olvidar cuando está cambiando una clase auxiliar interna a una accesible desde otro lugar, por lo que si está trabajando en un proyecto vinculado dinámicamente, también podría verificar eso.

Johann Studanski
fuente
2

en mi caso, declaró una variable estática en el archivo .h, como

//myClass.h
class myClass
{
static int m_nMyVar;
static void myFunc();
}

y en myClass.cpp, intenté usar este m_nMyVar. Recibió un error de ENLACE como:

error LNK2001: símbolo externo no resuelto "público: clase estática ... El archivo cpp relacionado con el error de enlace se ve así:

//myClass.cpp
void myClass::myFunc()
{
myClass::m_nMyVar = 123; //I tried to use this m_nMyVar here and got link error
}

Entonces agrego el siguiente código en la parte superior de myClass.cpp

//myClass.cpp
int myClass::m_nMyVar; //it seems redefine m_nMyVar, but it works well
void myClass::myFunc()
{
myClass::m_nMyVar = 123; //I tried to use this m_nMyVar here and got link error
}

entonces LNK2001 se fue.

Centavo
fuente
0

En mi caso, estaba usando enlaces incorrectos.
Se gestionó c ++ (cli) pero con exportación nativa. He agregado al enlazador -> entrada -> recurso de enlace de ensamblaje el dll de la biblioteca desde la cual se exporta la función. Pero la vinculación nativa de C ++ requiere que el archivo .lib "vea" las implementaciones en cpp correctamente, por lo que me ayudó a agregar el archivo .lib al enlazador -> input -> dependencias adicionales.
[Por lo general, el código administrado no usa dll export and import, usa referencias, pero esa era una situación única].

whats_wrong_here
fuente