c++ - programacion - Uno o más símbolos definidos de forma múltiple encontrados
manual de programacion android pdf (9)
Coloque la definición (cuerpo) en un archivo cpp y deje solo la declaración en un archivo ah. Incluya guardias que operen solo dentro de una unidad de traducción (también conocido como archivo fuente), no en todo su programa.
La regla de una definición de la norma C ++ establece que debe aparecer exactamente una definición de cada función no en línea que se utiliza en el programa. Entonces, otra alternativa sería hacer su función en línea.
DebugUtil.h
#ifndef DEBUG_UTIL_H
#define DEBUG_UTIL_H
#include <windows.h>
int DebugMessage(const char* message)
{
const int MAX_CHARS = 1023;
static char s_buffer[MAX_CHARS+1];
return 0;
}
#endif
Cuando intento ejecutar esto obtengo este error:
Terrain.obj: error LNK2005: "int __cdecl DebugMessage (char const *)" (? DebugMessage @@ YAHPBD @ Z) ya definido en Loodus.obj
Renderer.obj: error LNK2005: "int __cdecl DebugMessage (char const *)" (? DebugMessage @@ YAHPBD @ Z) ya definido en Loodus.obj
test.obj: error LNK2005: "int __cdecl DebugMessage (char const *)" (? DebugMessage @@ YAHPBD @ Z) ya definido en Loodus.obj
C: / Users / Tiago / Desktop / Loodus Engine / Debug / Loodus Engine.exe: error fatal LNK1169: uno o más símbolos definidos multiplicados encontrados
Pero, ¿por qué sucede esto? Tengo #ifndef #define y #endif en el encabezado, por lo que no deberían aparecer varias definiciones
Declara tus funciones en archivos C ++. Como definió su función en el archivo de encabezado y ese archivo de encabezado se incluye desde varios archivos de origen, se define para cada archivo fuente que lo incluye. Es por eso que se informa que se define en varios lugares.
Alternativamente, puede hacerlo en línea para que el código se inserte donde sea que se use en lugar de definirse como una función separada cada vez.
Eso solo evita inclusiones múltiples en el mismo archivo fuente; múltiples archivos de origen DebugMessage()
aún generará múltiples definiciones de DebugMessage()
. En general, no debe colocar funciones en archivos de encabezado o hacerlas static
(y usualmente en inline
, ya que de lo contrario no tiene sentido tener múltiples definiciones static
de la misma función).
Esta función se incluye en cada unidad de traducción y, como resultado, obtiene múltiples definiciones de la misma: cada archivo .obj contiene su propia copia. Cuando llega el momento de vincularlos, el vinculador muestra correctamente el error anterior.
Puedes hacer algunas cosas:
- Mueva la definición a un archivo .cpp y conserve solo la declaración en el encabezado.
- Use un espacio de nombre anónimo alrededor de la función en su archivo de encabezado (pero sepa que es un truco, aún tendrá múltiples definiciones, simplemente no habrá colisión de nombres).
- Marcarlo como en línea (aunque puede que no siempre funcione, solo si el compilador realmente elige alinearlo). Eso también es un truco por la misma razón que la anterior.
Haga la función en línea o declare la función en un archivo de encabezado y defínalo en un archivo cpp.
inline int DebugMessage(const char* message)
{
const int MAX_CHARS = 1023;
static char s_buffer[MAX_CHARS+1];
return 0;
}
EDITAR:
Como sugiere un comentario de Tomalak Geret''kal, es mejor utilizar mis últimas sugerencias que mi anterior y mover la declaración de la función a un archivo cpp.
Mueva la definición a un archivo .cpp.
Parece que está incluyendo DebugUtil.h en más de una unidad de traducción, y luego une esos objetos. Sin embargo, DebugUtil.h proporciona una definición para la función DebugMessage, por lo que esa definición existe en todas las unidades de traducción que incorporaron el encabezado. Como resultado, cuando vincula los objetos, el vinculador se queja con razón de que el símbolo está definido de forma múltiple.
Cambie DebugUtil.h para que declare DebugMessage a través de un prototipo, pero no proporcione una definición, y coloque la definición de DebugMessage en un archivo .c que compilará y vinculará con sus otros objetos.
100% seguro de que incluiste guardias correctamente pero sigues recibiendo un error de redefinición?
Para Visual Studio: estaba realmente frustrado porque estaba correctamente incluido guardias, solo para descubrir que el problema era Visual Studio. Si ha agregado el archivo a su proyecto, el compilador agregará el archivo dos veces, incluso si tiene guardias incluidas alrededor de su archivo de implementación y encabezado.
Si no usa Visual Studio exclusivamente, y digamos ... use code :: blocks a veces, es posible que desee #incluir el archivo cuando detecta la ausencia del entorno de Visual Studio.
DebugUtil.h :
----------------------
#ifndef _WIN32
#include "DebugUtil.c"
#endif
----------------------
Si está de acuerdo con incluir stdio.h, puede ser un poco menos hackish al respecto:
DebugUtil.h :
----------------------
#include <stdio.h>
#ifdef _MSC_VER
#include "DebugUtil.c"
#endif
----------------------
Referencia: Macros predefinidas, Visual Studio: https://msdn.microsoft.com/en-us/library/b0084kay.aspx
(Suponiendo que el código publicado sea un encabezado, incluido desde múltiples archivos .cpp)
Los resguardos de encabezado no lo protegen de las múltiples definiciones de tiempo de enlace. Independientemente de que se haya asegurado de que el encabezado solo aparezca una vez por cada Unidad de traducción, si tiene más de una Unidad de traducción, eso significará múltiples definiciones.
Escriba las definiciones en los archivos de origen y solo las declaraciones en los encabezados.
Las únicas excepciones son funciones en inline
, funciones definidas dentro de una definición de class
(¡aunque esto no se recomienda!) Y plantillas de función.