Jednotky překladu a propojení

V programu C++ lze symbol, například název proměnné nebo funkce, deklarovat libovolný početkrát v rámci oboru. Lze ho však definovat pouze jednou. Toto pravidlo je pravidlo "Jedno pravidlo definice" (ODR). Deklarace zavádí do programu (nebo znovu vytvoří) název spolu s dostatečnými informacemi, které později přidruží k definici. Definice představuje název a poskytuje všechny informace potřebné k jeho vytvoření. Pokud název představuje proměnnou, definice explicitně vytvoří úložiště a inicializuje ho. Definice funkce se skládá z podpisu a těla funkce. Definice třídy se skládá z názvu třídy následovaného blokem, který obsahuje seznam všech členů třídy. (Subjekty členských funkcí mohou být volitelně definovány samostatně v jiném souboru.)

Následující příklad ukazuje některé deklarace:

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

Následující příklad ukazuje některé definice:

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

Program se skládá z jedné nebo více jednotek překladu. Jednotka překladu se skládá z implementačního souboru a všech hlaviček, které obsahuje přímo nebo nepřímo. Implementační soubory mají obvykle příponu .cpp souboru nebo .cxx. Soubory hlaviček obvykle mají příponu .h nebo .hpp. Každá jednotka překladu je kompilována nezávisle kompilátorem. Po dokončení kompilace sloučí linker kompilované jednotky překladu do jednoho programu. Porušení pravidla ODR se obvykle zobrazují jako chyby linkeru. K chybám linkeru dochází v případě, že je stejný název definován ve více než jedné jednotce překladu.

Obecně platí, že nejlepším způsobem, jak nastavit, aby byla proměnná viditelná ve více souborech, je deklarovat ji v souboru hlaviček. Pak přidejte direktivu #include do každého .cpp souboru, který vyžaduje deklaraci. Přidáním ochrany zahrnutí kolem obsahu záhlaví zajistíte, že názvy, které hlavička deklaruje, jsou deklarovány pouze jednou pro každou jednotku překladu. Definujte název pouze v jednom souboru implementace.

V jazyce C++20 se moduly zavádějí jako vylepšená alternativa k souborům hlaviček.

V některých případech může být nutné deklarovat globální proměnnou nebo třídu v .cpp souboru. V takových případech potřebujete způsob, jak kompilátoru a linkeru sdělit, jaký druh propojení má název. Typ propojení určuje, zda je název objektu viditelný pouze v jednom souboru nebo ve všech souborech. Koncept propojení se vztahuje pouze na globální názvy. Koncept propojení se nevztahuje na názvy deklarované v rámci oboru. Obor je určen sadou uzavřených složených závorek, jako je funkce nebo definice třídy.

Externí vs. interní propojení

Bezplatná funkce je funkce , která je definována v globálním oboru názvů nebo oboru názvů. Nekonstanční globální proměnné a bezplatné funkce mají ve výchozím nastavení externí propojení. Jsou viditelné z jakékoli jednotky překladu v programu. Žádný jiný globální objekt nemůže mít tento název. Symbol s interním propojenímnebo bez propojení je viditelný pouze v rámci jednotky překladu, ve které je deklarována. Pokud má název interní propojení, může stejný název existovat v jiné jednotce překladu. Proměnné deklarované v definicích tříd nebo tělech funkcí nemají žádné propojení.

Globální název můžete vynutit, aby měl interní propojení tím, že ho explicitně deklaruje jako static. Toto klíčové slovo omezuje viditelnost na stejnou jednotku překladu, ve které je deklarována. V tomto kontextu znamená něco jiného než static při použití u místních proměnných.

Následující objekty mají ve výchozím nastavení interní propojení:

  • const Objekty
  • constexpr Objekty
  • typedef Objekty
  • static objekty v oboru názvů

Pokud chcete objektu const udělit externí propojení, deklarujte ho jako extern hodnotu a přiřaďte ji:

extern const int value = 42;

Další informace najdete na webu extern.

Viz také

Základní koncepty