Unidades de traducción y vinculación

En un programa de C++, un símbolo , por ejemplo, un nombre de variable o función, se puede declarar cualquier número de veces dentro de su ámbito, pero solo se puede definir una vez. Esta regla es la "regla de una definición" (ODR). Una declaración introduce (o vuelve a introducir) un nombre en el programa. Una definición introduce un nombre. Si el nombre representa una variable, una definición la inicializa explícitamente. Una definición de función consta de la firma más el cuerpo de la función. Una definición de clase consta del nombre de clase seguido de un bloque que enumera todos los miembros de clase. (Los cuerpos de las funciones miembro se pueden definir opcionalmente por separado en otro archivo).

En el ejemplo siguiente se muestran algunas declaraciones:

int i;
int f(int x);
class C;

En el ejemplo siguiente se muestran algunas definiciones:

int i{42};
int f(int x){ return x * i; }
class C {
public:
   void DoSomething();
};

Un programa consta de una o varias unidades de traducción. Una unidad de traducción consta de un archivo de implementación y todos los encabezados que incluye directa o indirectamente. Normalmente, los archivos de implementación tienen una extensión de archivo de cpp o cxx. Normalmente, los archivos de encabezado tienen una extensión de h o hpp. El compilador compila cada unidad de traducción de forma independiente. Una vez completada la compilación, el vinculador combina las unidades de traducción compiladas en un único programa. Las infracciones de la regla ODR suelen aparecer como errores del vinculador. Los errores del vinculador se producen cuando el mismo nombre tiene dos definiciones diferentes en unidades de traducción diferentes.

En general, la mejor manera de hacer que una variable sea visible en varios archivos es colocarla en un archivo de encabezado. A continuación, agregue #include directiva en cada archivo cpp que requiera la declaración. Al agregar protectores de include alrededor del contenido del encabezado, se asegura de que los nombres que declara solo se definen una vez.

En C++20, los módulos se presentan como una alternativa mejorada a los archivos de encabezado.

En algunos casos, puede ser necesario declarar una variable o clase global en un archivo cpp. En esos casos, necesita una manera de decir al compilador y al vinculador qué tipo de vinculación tiene el nombre. El tipo de vinculación especifica si el nombre del objeto se aplica solo a un archivo o a todos los archivos. El concepto de vinculación solo se aplica a los nombres globales. El concepto de vinculación no se aplica a los nombres declarados dentro de un ámbito. Un ámbito se especifica mediante un conjunto de llaves de cierre, como en definiciones de función o clase.

Vinculación externa frente a interna

Una función gratuita es una función que se define en el ámbito global o de espacio de nombres. De forma predeterminada, las variables globales no const y las funciones libres tienen vinculación externa; son visibles desde cualquier unidad de traducción del programa. Por lo tanto, ningún otro objeto global puede tener ese nombre. Un símbolo con vinculación interna o sin vinculación solo es visible dentro de la unidad de traducción en la que se declara. Cuando un nombre tiene vinculación interna, puede existir el mismo nombre en otra unidad de traducción. Las variables declaradas dentro de definiciones de clase o cuerpos de función no tienen vinculación.

Puede forzar que un nombre global tenga vinculación interna declarándose explícitamente como static . Esto limita su visibilidad a la misma unidad de traducción en la que se declara. En este contexto, static significa algo diferente de cuando se aplica a variables locales.

Los siguientes objetos tienen vinculación interna de forma predeterminada:

  • objetos const
  • objetos constexpr
  • typedefs
  • objetos estáticos en el ámbito del espacio de nombres

Para proporcionar una vinculación externa de objeto const, declare como extern y asígnele un valor:

extern const int value = 42;

Consulte extern para obtener más información.

Consulte también

Conceptos básicos