extern "C"
declara que algo tiene Enlace de lenguaje C. Esto es diferente de enlace externo y enlace interno. Por defecto, todo en un programa C++ tiene un enlace de lenguaje C++, aunque puede reiterarlo especificando extern "C++"
.
enlace externo significa que el nombre es visible para otros archivos fuente compilados por separado, suponiendo que incluya los encabezados correctos o proporcione las declaraciones correctas. Esto es lo que le permite definir una función foo
en a.cpp
, y llamarla desde b.cpp
. La mayoría de los nombres en el ámbito del espacio de nombres en un programa C++ tienen enlaces externos. Las excepciones son las que tienen enlace interno, y las que tienen sin enlace. Puede marcar explícitamente algo como que tiene un enlace externo especificando extern
. Esto es distinto de extern "C"
.
enlace interno significa que el nombre es exclusivo de la unidad de compilación actual y no puede acceder a la variable o función desde otro archivo de origen. Las variables de ámbito de archivo y las funciones declaradas static
tienen un enlace interno. Además, las variables enteras const
en el ámbito del espacio de nombres que se inicializan con una expresión constante tienen un enlace interno por defecto, aunque puede anularlo con un extern
explícito.
Finalmente, las variables locales y las clases tienen sin enlace. Los nombres son locales para la función en la que están declarados y no se puede acceder desde fuera de esa función. Puede usar extern
para indicar que realmente desea acceder a una variable en el ámbito del espacio de nombres.
Las plantillas no se pueden definir en el ámbito local, pero pueden tener un enlace interno o externo.
int i; // namespace scope variable has external linkage
extern int j; // explicitly mark j with external linkage
static int k; // k has internal linkage
int const n=42; // internal linkage
extern int const m=99; // external linkage
void foo(); // foo has external linkage; it may be defined in this source file or another
extern void foo(); // explicitly mark foo with external linkage
static void bar(); // bar has internal linkage, and must be defined in this source file
void foo(){} // definition of foo, visible from other source files
void bar(){} // definition of bar, not visible from other source files (internal linkage)
static void baz(){} // declare and define baz with internal linkage
template<typename T> void foobar(){} // foobar has external linkage
template<typename T>
static void foobaz(){} // foobaz has internal linkage
void wibble()
{
int i; // local, no linkage
extern int i; // references i, declared above with external linkage
}
extern "C"
{
int i2; // namespace scope variable has external linkage, and "C" linkage
extern int j2; // explicitly mark j2 with external linkage and "C" linkage
static int k2; // k2 has internal linkage and "C" linkage
int const n2=42; // internal linkage and "C" linkage
extern int const m2=99; // external linkage and "C" linkage
void foo2(); // foo2 has external linkage and "C" linkage
static void bar2(); // bar2 has internal linkage and "C" linkage
void foo2(){} // definition of foo2, still with external linkage and "C" linkage
void bar2(){} // definition of bar2, still with internal linkage and "C" linkage
static void baz(){} // declare and define baz with internal linkage
}
El mensaje de error es correcto --- plantillas no pueden tener extern "C"
vinculación.
En el nivel básico, las plantillas no pueden tener el enlace extern "C"
porque no son compatibles con C. En particular, una plantilla no solo define una sola clase o función, sino una familia de clases o funciones que comparten el mismo nombre , pero se distinguen por sus parámetros de plantilla.
Solo se puede declarar una función con un nombre extern "C"
. Esto tiene sentido cuando piensas en el cambio de nombre --- en C, una función foo
se llama normalmente foo
o _foo
en la tabla de símbolos.En C++ puede haber muchas sobrecargas de foo
, por lo que la firma se incorpora al nombre "destrozado" en la tabla de símbolos, y puede obtener $3fooV
o foo$void
o alguna otra cosa para distinguir foo(void)
de foo(int)
y así sucesivamente. En C++, la única sobrecarga que está marcada extern "C"
se destroza de acuerdo con el esquema C para la plataforma determinada, mientras que las otras sobrecargas mantienen su nombre normal.
Declarar una plantilla extern "C"
requeriría que todos los ejemplificaciones ser extern "C"
, que de este modo contradice el "sólo una función con un nombre dado puede ser extern "C"
" regla.
Aunque C no tiene nombre para struct
s, solo puede haber un struct
con un nombre de pila. La prohibición de extern "C"
para plantillas de clase también tiene sentido --- una plantilla define una familia de clases con el mismo nombre, ¿cuál corresponde a la C struct
?
Acabo de notar que ha agregado una recompensa por la pregunta. Lo cual me parece extraño ya que considero que la respuesta que proporcioné es correcta y completa. ¿Qué es lo que todavía no entiendes? - He notado que también eliminó la parte inicial de la pregunta, haciendo que la mayoría de la respuesta sea inútil ... Debe considerar agregar comentarios o una pregunta diferente si todavía tiene dudas. Cambiar la pregunta no ayuda a nadie: las personas que ya han respondido no reciben notificaciones, las personas que navegan por las q & a estarán desconcertadas por las respuestas que no están relacionadas ... –
Volvió a la versión antes de la eliminación, para que tenga más sentido . – Suma
@David: Parece que BE Student está interesado en dar puntos específicamente al USUARIO. –