Share via


Unidades de tradução e vinculação

Em um programa C++, um símbolo, por exemplo, uma variável ou nome de função, pode ser declarado diversas vezes dentro de seu escopo. No entanto, ele só pode ser definido uma vez. Essa regra é a "Regra de Uma Definição" (ODR). Uma declaração introduz (ou reintroduz) um nome no programa, junto à informações suficientes para associar o nome a uma definição mais tarde. Uma definição introduz um nome e fornece todas as informações necessárias para criá-lo. Se o nome representa uma variável, uma definição cria explicitamente o armazenamento e o inicializa. Uma definição de função consiste na assinatura com o corpo da função. Uma definição de classe consiste no nome da classe seguido por um bloco que lista todos os membros da classe. (Opcionalmente, os corpos das funções de membro podem ser definidos separadamente em outro arquivo.)

O exemplo a seguir mostra algumas declarações:

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

O exemplo a seguir mostra algumas definições:

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

Um programa consiste em uma ou mais unidades de tradução. Uma unidade de tradução consiste em um arquivo de implementação e todos os cabeçalhos que ele inclui direta ou indiretamente. Os arquivos de implementação normalmente têm uma extensão de arquivo de .cpp ou .cxx. Os arquivos de cabeçalho normalmente têm uma extensão de .h ou .hpp. Cada unidade de tradução é compilada independentemente pelo compilador. Depois que a compilação é concluída, o vinculador mescla as unidades de tradução compiladas em um único programa. As violações da regra de ODR normalmente aparecem como erros do vinculador. Os erros do vinculador ocorrem quando o mesmo nome é definido em mais de uma unidade de tradução.

Em geral, a melhor maneira de tornar uma variável visível em vários arquivos é declará-la em um arquivo de cabeçalho. Em seguida, adicione uma diretiva #include em cada arquivo .cpp que exija a declaração. Ao adicionar proteções de inclusão em torno do conteúdo do cabeçalho, você garante que os nomes declarados por cabeçalho sejam declarados apenas uma vez em cada unidade de tradução. Definir o nome em apenas um arquivo de implementação.

No C++20, os módulos são apresentados como uma alternativa melhorada aos arquivos de cabeçalho.

Em alguns casos, pode ser necessário declarar uma variável ou classe global em um arquivo .cpp. Nesses casos, você precisa de uma maneira de informar ao compilador e ao vinculador qual tipo de vínculo o nome tem. O tipo de vínculo especifica se o nome do objeto é visível apenas em um arquivo ou em todos os arquivos. O conceito de vínculo se aplica apenas a nomes globais. O conceito de vínculo não se aplica a nomes declarados dentro de um escopo. Um escopo é especificado por um conjunto de chaves delimitadoras, como nas definições de função ou classe.

Vínculo externo versus interno

Uma função gratuita é uma função que é definida no escopo global ou de namespace. Variáveis globais não const e funções gratuitas por padrão possuem vínculo externo e elas são visíveis de toda unidade de tradução no programa. Nenhum outro objeto global pode ter esse nome. Um símbolo com vínculo interno ou sem vínculos é visível somente dentro da unidade de tradução na qual foi declarado. Quando um nome tem vínculo interno, o mesmo nome pode existir em outra unidade de tradução. Variáveis declaradas dentro de definições de classe ou corpos de função não possuem vínculo.

Você pode impor um nome global a ter vínculo interno ao declará-lo explicitamente como static. Essa palavra-chave limita a visibilidade dela à mesma unidade de tradução na qual ela foi declarada. Nesse contexto, static significa algo diferente de quando aplicado a variáveis locais.

Por padrão, os seguintes objetos têm vínculo interno:

  • Objetos const
  • Objetos constexpr
  • Objetos typedef
  • Objetos static no escopo do namespace

Para fornecer um vínculo externo ao objeto const, declare-o como extern e atribua um valor a ele:

extern const int value = 42;

Para obter mais informações, consulte extern.

Confira também

Conceitos básicos