使用未命名的命名空間代替靜態全域性變數

2022-09-17 05:57:11 字數 1972 閱讀 8965

當你的程式連線時,程式越大,越有可能在本地檔案中遇到名字衝突。在原始檔中宣告的函式或變數被轉化成本地的編譯單元,可能與另乙個編譯單元中宣告的相同函式或變數產生名字衝突。這是因為所有沒有宣告為 static 的符號具有外部鏈結性,所以它們的名字在整個程式中必須是唯一的。針對該問題,典型的c 解決方法是將這些符號宣告為 static,將它們的鏈結性由外部改為內部,使它們只在乙個編譯單元中。在本節中,我們將看看針對該問題 c++ 的解決方法。

在本節中,我們將討論一些概念,如全域性函式,靜態函式和變數,命名空間和編譯單元。除這些之外,你還需要理解內部和外部鏈結的不同;這是本節的關鍵。

當你遇到這樣的情況,需要將全域性符號宣告成 static 以避免鏈結問題時,優先使用未命名命名空間:

在你的原始檔中宣告乙個沒有名字的命名空間。

將全域性函式或變數的定義放在未命名命名空間中,無須將它們宣告為 static。

下面的例子顯示了 2 個在不同編譯單元的被稱為 print()的 2 個函式;每乙個都定義在乙個未命名命名空間中:

1

// file1.cpp

2namespace

38}  910

void

file1_run

()11

1415

// file2.cpp

16namespace

1722} 

2324

void

file2_run

()25

當在乙個編譯單元中宣告乙個函式時,它具有外部鏈結性。這就是說兩個不同編譯單元中的兩個具有相同名字的函式將生成乙個鏈結錯誤,因為不能存在具有相同名字的兩個符號。這個問題在 c 中已經解決,在 c++ 中也解決了部分,就是將函式或變數宣告成 static 從而將它的鏈結性從外部改為內部。在這種情況下,它的名字不再匯出到外部的編譯單元中,從而避免了這個鏈結問題。

c++ 中合適的解決方法是使用未命名命名空間。當你定義了像之前上面顯示的命名空間時,編譯器將其轉換為如下形式:

1

// file1.cpp

2namespace _unique_name_ 

3using

namespace _unique_name_;

4namespace _unique_name_

510}  

1112

void

file1_run

()13

第一,宣告了乙個具有唯一名字的命名空間()。此時該命名空間是空的,這一行的目的是建立該命名空間。

第二,using 指示符將 unique_name 命名空間中的所有東西引入到當前命名空間。

第三,該命名空間使用編譯器生成的名字,定義與原來的**一樣(當它沒有名字時)。

通過在未命名的命名空間中定義編譯單元中的 print() 函式,它們只有本地可見性,然而它們的外部鏈結性不再產生鏈結錯誤,應為它們現在有了外部唯一的名字。

在呼叫模板的可能更加晦澀的情況下,未命名命名空間也能正常工作。模板引數的名字不能有內部鏈結性,因此不能使用 static 變數。換句話說,在未命名命名空間中的符號具有外部鏈結性並且可以用作模板引數。這個問題顯示在下面的例子中,宣告的 t1 產生乙個編譯錯誤,因為非型別引數表示式具有內部鏈結性。然而,t2 是正確的,因為 size2 具有外部鏈結性:

1

template

const& size>

2class

test {};34

static

int size1 = 10;56

namespace710

11testt1; // error

12testt2; // ok

- - - end - - -

命名空間的使用

在我們寫大的程式時,上萬行,十萬行,或者更多時,那時可能 那麼,如何去解決這樣的錯誤呢?我們又不能邊寫邊告訴別人,哎,我這變數名我用了,你不能再用了 哪的多麼麻煩啊!而且,那麼多的資料得定義多麼多的名字啊,我想定個名字也得需要很多時間吧 命名空間的一般形式 namesapce 名字 下面我們來編寫乙...

命名空間的使用

引入的原因在c 中,名稱可以是變數 函式 結構 列舉以及類和機構的成員。隨著工程的增大,名稱相互衝突的可能性也隨著增加。在使用多個廠商的類庫時可能導致名稱衝突。c 提出了namespace命名空間解決方法,只要再加一層空間就可以了。為什麼stl程式中一般要加入using namespcae std ...

命名空間的使用

include include 命名空間的定義 定義一塊命名空間,名字叫 namea namespace namea namespace aa namespace nameb using namespace namea int g b 全域性的g b 命名空間的使用 1 通過命名空間名字和 域解析符...