c++ - literatura - funcion estatica en fisica
C++ extern keyword en las funciones. ¿Por qué no solo incluir el archivo de encabezado? (5)
1) Puede no tener un archivo de encabezado. Pero sí, en general, para proyectos grandes, debe tener un archivo de cabecera si varias unidades de traducción van a usar esa función (no se repita).
2) El enlazador busca a través de todos los archivos de objetos y bibliotecas sobre las funciones y otros símbolos.
Si lo entiendo correctamente, esto significa
extern void foo();
que la función foo se declara en otra unidad de traducción.
1) ¿Por qué no solo # incluye el encabezado en el que se declara esta función?
2) ¿Cómo sabe el vinculador dónde buscar la función en el tiempo de enlace?
editar: Tal vez debería aclarar que la declaración anterior se sigue utilizando la función
foo();
Nunca se define en esta unidad de traducción.
1) No sé por qué necesitaría esto para una función. Tal vez alguien más puede intervenir.
2) El enlazador determina esto yendo a través de todos los archivos de objeto y verificando los símbolos dentro de cada archivo de objeto. Supongo que, dependiendo de su vinculador, el orden de búsqueda exacto puede variar.
Para GNU binutils ''ld, todos los archivos de objetos y bibliotecas que aparecen en la línea de comando del enlazador después de que el objeto que contiene el símbolo faltante se busquen de izquierda a derecha y se selecciona el primer símbolo encontrado.
Ejemplo 1:
- ao: usa foo (), barra ()
- liba - proporciona barra ()
- libb - proporciona foo ()
$> ld ao -la -lb
dará como resultado que se busquen símbolos indefinidos. A continuación, ld pasará por las bibliotecas de izquierda a derecha para buscar estos símbolos y encontrará barras en liba y foo en libb.
Esto puede conducir a problemas extraños en dependencias circulares:
Ejemplo 2:
- ao - usa la barra ()
- liba - proporciona barra (), usa foo ()
- libb - proporciona foo (), usa barra ()
Ahora, existe una dependencia circular entre liba y libb y el enlace fallará:
$> ld ao -la -lb
porque al buscar a través de los símbolos indefinidos en libb, ld determinará que no hay ninguna otra lib a la derecha de -lb que proporcione este símbolo. Esto puede solucionarse al menos de dos maneras:
1) enlace liba dos veces: $> ld ao -la -lb -la
2) use la función de agrupamiento de ld $> ld ao --start-group -la -lb --end-group
En el caso 2), la agrupación le dice a ld que busque a través de todos los símbolos en todas las libs que pertenecen a este grupo.
Como otros ya han indicado, la palabra clave extern
se usa para indicar que el nombre (una variable o función) tiene una vinculación externa, lo que significa que el nombre hace referencia al mismo objeto en todo el programa. Además, este es el valor predeterminado para las variables y funciones definidas en el alcance del archivo, por lo que este uso es superfluo.
Hay otro uso de la palabra clave extern que dice así:
extern "C" void foo();
Esto significa que la función foo
se vinculará utilizando las convenciones de C para la vinculación (tal vez porque esta es una función definida en una biblioteca C o es una función destinada a ser llamada por los programas C).
No, esto significa que la función foo
se declara con un enlace externo . Enlace externo significa que el nombre foo
refiere a la misma función en todo el programa. Donde la función está definida no importa. Se puede definir en esta unidad de traducción. Se puede definir en otra unidad de traducción.
Usar palabras clave extern
como se muestra en su ejemplo es superfluo. Las funciones siempre tienen un enlace externo por defecto. Lo anterior es 100% equivalente a solo
void foo();
En cuanto al enlazador, cuando el enlazador vincula el programa, simplemente busca en todas partes . Mira a través de todas las definiciones hasta que encuentra la definición de foo
.
Ya significa que sin la palabra clave extern. Las funciones tienen un enlace externo por defecto, a menos que las declare estáticas.
El uso de prototipos de funciones está bien, pero es fácil equivocarse. El error del enlazador que obtendrá no es tan fácil de diagnosticar cuando redefine la implementación de la función. El vinculador no sabe dónde buscar, es su trabajo darle un archivo de objeto que contenga la definición de la función para mantenerlo feliz.