¿Por qué "extern const int n;" no funciona como se esperaba?


Mi proyecto consta de solo dos archivos fuente:

A.cpp:

const int n = 8;

B.cpp:

extern const int n;

int main()
{
    // error LNK2001: unresolved external symbol "int const n" (?n@@3HB)
    int m = n; 
}

Sé que hay varios métodos para hacer que funcione; sin embargo, me pregunto POR QUÉ no funciona?

Author: xmllmx, 2013-02-15

5 answers

Es porque const implica enlace interno por defecto, por lo que su "definición" no es visible fuera de la unidad de traducción donde aparece.

En este caso, la mejor solución es poner la declaración (extern int const n;) en un archivo de encabezado, e incluirlo en tanto a.cpp como b.cpp. El vínculo está determinado por el primera declaración que ve el compilador, por lo que la definición posterior en a.cpp tendrá el enlace (externo) correcto.

Alternativamente, puede forzar el enlace en el definición:

extern int const n = 8;

A pesar de la extern, esto sigue siendo una definición; cualquier cosa con un inicializador fuera de una definición de clase es una definición.

 45
Author: James Kanze,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-15 12:38:15

const y constexpr las variables en C++ tienen enlace interno (y por lo tanto no son accesibles en otra unidad de compilación) si no se declaran también extern (ya sea en la definición o en una declaración anterior).

En C, no es el caso (bueno C no tiene constexpr) por lo que su código es válido, y más se puede poner extern en una definición.

Así que si desea escribir código que es a la vez C y C++ (y las dos declaraciones probablemente deberían venir de la misma cabecera que James señaló fuera):

// a.cpp
extern const int n;
const int n = 8;

// b.cpp
extern const int n;

int main()
{

    int m = n; 
}

Si no lo haces

// a.cpp
extern const int n = 8;

También Es posible

 5
Author: AProgrammer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-15 12:47:02

Declararlo extern en a.cpp y solo uso sin extern en b.cpp:

A. h

extern const int n ;

A.cpp

#include "a.h"
...
const int n= 8

B.cpp:

#include "a.h"
...


int main()
{        
    int m = n; 
}
 2
Author: Gjordis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-15 12:36:01

To share a const object among multiple files, you must define the variable as extern.

To define a single instance of a const variable, we use the keyword extern on both its definition and declaration(s):

De estas reglas solo necesita agregar la palabra clave extern en su definición. ya lo tienes en la declaración.

 2
Author: Arpit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-15 12:44:06

Si las otras respuestas aquí no hacen el truco, puede ser el caso de que tenga sus definiciones en diferentes espacios de nombres... si la compilación pasa, y obtienes un error de enlazador undefined symbol:

  • compruebe el espacio de nombres del símbolo indefinido; ese es el espacio de nombres efectivo para la declaración extern const int n.
  • asegúrese de que es su espacio de nombres efectivo donde hace la definición const int n = 8.
 1
Author: einpoklum,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-04-26 16:50:54