error LNK2005, ya definido?

Tengo 2 archivos, A.cpp y B.cpp, en una aplicación de consola Win32.

Ambos archivos contienen solo las siguientes 2 líneas de código:

#include "stdafx.h" int k; 

Al comstackr produce el error

 Error 1 error LNK2005: "int k" (?a@@3HA) already defined in A.obj 

No entiendo lo que está pasando.

¿Alguien puede explicarme esto?

¿Por qué este error?

Rompiste la regla de una definición y, por lo tanto, el error de vinculación.

Las soluciones sugeridas:


Si necesita la misma variable nombrada en los dos archivos cpp, entonces necesita usar el espacio de nombres Nameless (espacio de nombre anónimo) para evitar el error.

 namespace { int k; } 

Si necesita compartir la misma variable en múltiples archivos, entonces necesita usar extern .

Ah

 extern int k; 

A.cpp

 #include "Ah" int k = 0; 

B.cpp

 #include "Ah" //Use `k` anywhere in the file 

add / FORCE: MULTIPLE a las opciones de línea de comando del enlazador.

Desde MSDN : “Use / FORCE: MULTIPLE para crear un archivo de salida, ya sea que LINK encuentre o no más de una definición para un símbolo”.

Si desea que ambos hagan referencia a la misma variable, uno de ellos debe tener int k; , y el otro debería tener extern int k;

Para esta situación, normalmente coloca la definición ( int k; ) en un archivo .cpp y coloca la statement ( extern int k; ) en un encabezado, para incluirla donde sea que necesite acceder a esa variable.

Si desea que cada k sea ​​una variable separada que tenga el mismo nombre, puede marcarlas como static , como: static int k; (en todos los archivos, o al menos en todos los archivos). Alternativamente, puede usar un espacio de nombre anónimo:

 namespace { int k; }; 

Nuevamente, en todos menos en uno de los archivos.

En C, el comstackdor generalmente no es tan exigente con esto. Específicamente, C tiene un concepto de “definición tentativa”, así que si tiene algo como int k; dos veces (en los mismos o en los archivos fuente separados), cada uno será tratado como una definición tentativa, y no habrá conflicto entre ellos. Sin embargo, esto puede ser un poco confuso porque todavía no puede tener dos definiciones que incluyan inicializadores; una definición con un inicializador es siempre una definición completa, no una definición tentativa. En otras palabras, int k = 1; aparecer dos veces sería un error, pero int k; en un lugar e int k = 1; en otro no lo haría. En este caso, el int k; se trataría como una definición tentativa y el int k = 1; como definición (y ambos se refieren a la misma variable).

Suponiendo que desea que ‘k’ tenga un valor diferente en diferentes archivos .cpp (de ahí que lo declare dos veces), intente cambiar ambos archivos a

 namespace { int k; } 

Esto garantiza que el nombre ‘k’ identifica de forma única ‘k’ en las unidades de traducción. La versión anterior static int k; es obsoleto.

Si desea que apunten al mismo valor, cambie uno a extern int k; .

Ambos archivos definen la variable k como un entero ( int ).

Como resultado, el enlazador ve dos variables con el mismo nombre, y no está seguro de cuál usar si alguna vez se refiere a k .

Para solucionar esto, cambie una de las declaraciones a:

 extern int k; 

Eso significa: “k es un número entero, declarado aquí, pero definido externamente (es decir, el otro archivo)”.

Ahora solo hay una variable k , a la que se puede hacer referencia de forma adecuada mediante dos archivos diferentes.

Y si desea que estas unidades de traducción compartan esta variable, defina int k; en A.cpp y poner extern int k; en B.cpp.

El enlazador le dice que tiene la variable k definida varias veces. De hecho, tiene una definición en A.cpp y otra en B.cpp. Ambas unidades de comstackción producen un archivo de objeto correspondiente que el vinculador usa para crear su progtwig. El problema es que en tu caso el enlazador no sabe qué definición de k usar. En C ++ puedes tener solo una definición de la misma construcción (variable, tipo, función).

Para solucionarlo, tendrá que decidir cuál es su objective

  • Si desea tener dos variables, ambas llamadas k , puede usar un espacio de nombre anónimo en ambos archivos .cpp, luego consulte k como lo está haciendo ahora:

.

 namespace { int k; } 
  • Puede cambiar el nombre de uno de los k a otra cosa, evitando así la definición duplicada.
  • Si desea tener una sola definición de k y usarla en ambos archivos .cpp, debe declarar en una como extern int k; y déjalo como está en el otro. Esto le indicará al vinculador que use la definición única (la versión sin cambios) en ambos casos. extern implica que la variable se define en otra unidad de comstackción.