共用方式為


編譯單位和連結

在C++程式中,符號,例如變數或函式名稱,可以在其範圍內宣告任何次數。 不過,它只能定義一次。 此規則是「一個定義規則」(ODR)。 宣告會將名稱引入程式,以及足夠的資訊,以便稍後將名稱與定義產生關聯。 定義引進名稱,並提供建立它所需的所有資訊。 如果名稱代表變數,定義會明確建立記憶體並初始化它。 函 式定義 是由簽章加上函式主體所組成。 類別定義是由類別名稱所組成,後面接著列出所有類別成員的區塊。 (成員函式的主體可選擇性地在另一個檔案中個別定義。

下列範例顯示一些宣告:

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

下列範例顯示一些定義:

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

程式是由一或多個 翻譯單位所組成。 翻譯單元包含實作檔案及其直接或間接包含的所有標頭。 實作檔案通常擴展名為 .cpp.cxx。 標頭檔通常具有 或.h.hpp擴展名。 編譯程式會獨立編譯每個轉譯單位。 編譯完成之後,鏈接器會將編譯的翻譯單位合併成單 一程式。 ODR 規則的違規通常會顯示為連結器錯誤。 在多個翻譯單位中定義相同名稱時,就會發生連結器錯誤。

一般而言,讓多個檔案可見變數的最佳方式是在頭檔中宣告變數。 然後在每個#include需要宣告的檔案中新增 .cpp 指示詞。 藉由在標頭內容周圍新增 include guard ,您可確保標頭宣告的名稱只會針對每個轉譯單位宣告一次。 在一個實作檔案中定義名稱。

在 C++20 中, 模組 會引進為標頭檔改善的替代方案。

在某些情況下,您可能需要在檔案中 .cpp 宣告全域變數或類別。 在這些情況下,您需要一種方式來告訴編譯程式和連結器名稱具有何種 連結 。 連結的類型會指定物件的名稱只顯示在一個檔案中或所有檔案中。 連結的概念僅適用於全域名稱。 連結的概念不適用於範圍內宣告的名稱。 範圍是由一組括住大括弧所指定,例如在函式或類別定義中。

外部與內部連結

免費函式是定義於全域或命名空間範圍的函式。 根據預設,非常數全域變數和免費函式具有 外部連結;它們可從程式中的任何轉譯單位看到。 沒有其他全域物件可以有該名稱。 具有內部連結或沒有連結的符號只能在宣告它的轉譯單位內顯示。 當名稱具有內部連結時,同名可能會存在於另一個轉譯單位中。 類別定義或函式主體內宣告的變數沒有連結。

您可以藉由明確將全域名稱宣告為 static,強制具有內部連結。 此關鍵詞會將其可見度限制為宣告所在的相同翻譯單位。 在此內容中, static 表示與套用至局部變數時不同的專案。

根據預設,下列物件具有內部連結:

  • const 物件
  • constexpr 物件
  • typedef 物件
  • static 命名空間範圍中的物件

若要提供 const 物件外部連結,請將它宣告為 extern ,併為其指派值:

extern const int value = 42;

如需詳細資訊,請參閱extern

另請參閱

基本概念