2012-04-20 10 views
8

Siempre obtengo un error de compilación cuando intento definir una función C en el archivo de encabezado justo encima de la interfaz de la clase.¿Por qué no puedo definir funciones C simples en el archivo de encabezado?

pero cuando hago lo mismo en el archivo de implementación y doy una declaración en el encabezado. Las cosas funcionan.

Quería saber, ¿por qué es así porque he definido enums, structs, NSStrings constantes en el archivo de cabecera, entonces ¿por qué no las funciones C?

Respuesta

14

Esto tiene que ver con la forma en que funciona el enlazador C (o el editor de enlaces). Cuando el compilador de C encuentra una definición de función, prepara el código ensamblador que implementa esa función y lo marca con un símbolo que le dice al enlazador "aquí es donde comienza la función con este nombre". El símbolo generalmente se nombra con un guión bajo seguido del nombre de la función, p. Ej. _printf.

Si se define la función en un archivo de cabecera, a continuación, todos los archivos .c o .m que importa esta cabecera compilará la función, y hará que el compilador emita el mismo símbolo. El vinculador espera encontrar solo una instancia de cada símbolo, por lo que este es un error.

Esto no está relacionado con la existencia de guardias #include, o al usar #import en lugar de #include. El compilador de C funciona en unidades de traducción individuales , lo que significa archivos fuente individuales. Las estrategias de preprocesador le impiden incluir el mismo archivo de encabezado dos veces en un solo archivo de origen, pero no hacen nada para coordinar las actividades en varios archivos. Eso significa que es válido incluir los mismos encabezados en diferentes archivos fuente: también significa que cuando compila diferentes archivos, pueden (legítimamente) contener el mismo símbolo.

Es tarea del editor de enlaces juntar estos archivos, resolviendo cualquier referencia a símbolos desconocidos en tiempo de compilación. Si intenta vincular objetos (el nombre de las unidades de traducción compiladas y ensambladas) que tienen el mismo símbolo en el mismo archivo, biblioteca compartida o ejecutable, entonces obtendrá el error que está viendo aquí.

Soluciones:

  • No defina la función en la cabecera, simplemente declarar allí y definirlo en un archivo de aplicación; como ya has descubierto, esto funciona
  • Defina la función en el encabezado, pero solo incluya ese encabezado en un lugar de su código. Esto a menudo es inaceptable por motivos de diseño.
  • Defina la función en el encabezado con el modificador inline. El compilador simplemente copia las funciones en línea en la función a la que se llama, por lo que nunca se emite un símbolo del enlazador. Esto tiene sus propias compensaciones que usted may wish to read more about.
+0

shuldn't #import (en lugar de #include) incluir un archivo una sola vez? Y ... también puedes usar incluir guardias (#ifndef MYFILE_H #define MYFILE_H ... #endif) – Francesco

+1

Gracias por la pregunta @Francesco, he incorporado una respuesta arriba (la versión corta es que las protecciones del preprocesador no se detendrán) obteniendo errores de enlace). –

+0

Pero ... ¿estamos hablando de definiciones o declaraciones de funciones C? Porque ... lo he intentado con una definición de función en un archivo .h, e incluyo el doble del archivo. Si uso #include obtengo "redefinición" de la función. Si uso # import o guardias (en cada archivo .h) no obtengo ningún error ... – Francesco

Cuestiones relacionadas