我從來沒有使用過我的代碼的命名空間。 (除了使用STL功能外)爲什麼以及如何在C++中使用名稱空間?
- 除了避免名稱衝突之外,是否有其他理由使用名稱空間?
- 我是否必須將名稱空間範圍內的聲明和定義括起來?
我從來沒有使用過我的代碼的命名空間。 (除了使用STL功能外)爲什麼以及如何在C++中使用名稱空間?
Here是一個很好的理由(除了明顯的你說的)。
由於命名空間可以是不連續和跨翻譯單元傳播,它們也可以用來實現細節分離接口。名稱空間中的名稱的
定義既可以在相同的命名空間或以任何封閉的命名空間來提供(使用完全限定的名稱)。
是不是名稱衝突足夠的原因? ADL的微妙之處,尤其是運營商超負荷的情況,是另一回事。
這是最簡單的方法。你也可以用命名空間爲名字加前綴,例如my_namespace :: name,當定義時。
你能想到的名字空間的邏輯分離單位的申請,並在此邏輯意味着,假設我們有兩個不同的類,把每一個這兩個類的文件,但是當你發現這些類共享足以在一個類別下分類的內容,這是使用名稱空間的一個強有力的理由。
它可以幫助你更好的理解。
如:
std::func <- all function/class from C++ standard library
lib1::func <- all function/class from specific library
module1::func <-- all function/class for a module of your system
你也可以把它看作你的系統模塊。
它也可以是有用的一個書面文件(如:你可以很容易地記錄在doxygen的命名實體)
這往往被忽視一個原因是,只需改變一個單一的代碼行,選擇了另外一個命名空間您可以選擇另一組函數/變量/類型/常量 - 例如協議的另一個版本,或單線程與多線程支持,OS支持平臺X或Y - 編譯和運行。通過包含具有不同聲明的標題,或者使用#defines
和#ifdefs
,但是這會粗略地影響整個翻譯單元,並且如果鏈接不同版本,您可能會得到未定義的行爲,可能會實現同樣的效果。使用命名空間,您可以通過使用僅在活動命名空間內應用的命名空間進行選擇,或者通過命名空間別名來進行選擇,以便它們僅應用於使用該別名的位置,但它們實際上已解析爲不同的鏈接器符號,因此可以組合使用未定義的行爲。這可以以類似於模板策略的方式使用,但影響更隱含,自動且普及 - 一種非常強大的語言功能。
UPDATE:解決marcv81的評論...
爲什麼不使用的接口有兩個實現?
「接口+實施」的概念有什麼選擇一個命名空間別名以上是幹什麼的,但如果你的意思是明確運行多態性與虛擬調度:
產生的庫或可執行文件沒有按」 t需要包含所有的實現並且在運行時不斷地直接調用所選的實現
作爲一個實現的合併,編譯器可以使用無數優化,包括inlinin g,死代碼消除,並且「實現」之間的不同之處的常量可以用於例如陣列的尺寸 - 允許自動存儲器分配而不是較慢的動態分配的
不同的命名空間具有支持使用相同語義,但不結合於支持完全相同的一組函數簽名作爲爲的情況下虛擬調度
與命名空間,你可以定製提供非成員函數和模板:這是不可能的虛擬調度(和非成員函數對稱操作符重載幫助 - 例如支持22 + my_type
以及my_type + 22
)
不同的名稱空間可以指定不同的類型以用於某些目的(例如,散列函數可能會在一個名稱空間中返回一個32位值,而在另一個名稱空間中會返回一個64位值),但虛擬接口需要統一靜態類型,這意味着笨拙和高開銷間接性,如boost::any
或boost::variant
或最壞情況選擇其中,高序位有時是毫無意義的
虛擬調度往往涉及脂肪接口和笨拙的錯誤處理之間的妥協:與命名空間還有的選項根本就沒有提供命名空間的地方是沒有意義的功能,給人一種編譯期實施必要的客戶端移植工作
我做在C++中沒有像你那麼多的經驗,但這對我來說聽起來相當邪惡。爲什麼不使用兩個實現的接口?我看不出使用名稱空間的好處。請原諒這個評論的可能天真:) – marcv81 2015-07-07 03:07:35
@ marcv81:上面的一些解釋...總是歡迎問題/想法。乾杯。 – 2015-07-07 03:59:31
Mindblowing,+1。我瞭解速度/大小優化。爲了提高靈活性,你說我們可以使用例如C++ 11「auto foo = bar()」,其中bar()具有不同的返回類型,具體取決於所使用的名稱空間?盡我所知,我不確定我會在工作中嘗試它:)我可以看到的一個缺點是單元測試:我寧願不鏈接超過1個可執行文件來運行我的測試,但我同意它不是一個阻止程序爲所有人。順便說一句,我喜歡避免使用#ifdefs。 – marcv81 2015-07-07 06:38:48