C++11新特性(79)-內聯名稱空間(inline namespace)
名稱空間簡介
隨著軟體開發規模的擴大,類名,函式名重複的可能性也越來越大。最樸素的解決辦法就是改名,這種方法在向已經存在的類庫中新增程式碼時問題不大,但是如果是將兩個從未謀面的程式碼庫結合在一起時就不再適用了。
C++解決這個問題的辦法就是引入名稱空間。假設有下面兩個名稱空間:
程式碼中分別定義了std_namespace1和lstd_namespace2兩個名稱空間。在兩個名稱空間內分別定義了相同名稱的Normal類。這兩個類的成員函式是否一樣其實不重要,這裡姑且使用了相同的名稱。
有了名稱空間以後,使用【名稱空間名稱::類名】的方式,就可以對這兩個同名的Normal類加以區分了。
如果使用using語句,可以讓某個名稱空間的內容釋放出來,就好像它們都存在與外層名稱空間一樣。
這種方法的一個弊端就是有可能發生類名重複的情況,這時就需要程式設計師來小心控制了。
內聯名稱空間
C++11中引入了內聯名稱空間(inline namespace),它的特點就是不需要使用using語句就可以直接在外層名稱空間使用該名稱空間內部的內容,而且無需使用名稱空間字首。先看程式碼:
內聯名稱空間的宣告方法就是在原來的宣告語法前面增加inline關鍵字。除此之外上面程式碼還有以下特點:
-
兩處宣告的名稱空間同名,它們同屬一個名稱空間。這是C++名稱空間從來就有的特性。
-
第一次宣告名稱空間時使用了inline關鍵字,這叫顯式內聯;第二次沒有使用inline關鍵字,但是由於第一次已經聲明瞭inline,這裡宣告的還是內聯名稱空間。這種情況成為隱式內聯。
內聯名稱空間宣告之後,就可以在外層名稱空間不適用字首而直接使用它們了。
上述程式碼中test_inline_namespace處在linline_namespace1的外層,所以可以直接使用Inline1和Inline2。test_inline_namespace2處在更外層,這時也只是需要使用外層名稱空間inline_test字首即可。
看起來inline_namespace就像不存在一樣。
嚴肅的問題
前面提到內聯名稱空間就像不存在一樣,那麼就產生了一個嚴肅的問題:它有什麼用?為了回答這個問題,我們舉一個更加接近實際開發的例子。假設有如下類庫程式碼:
很簡單的類,當然使用這些類的程式碼也同樣簡單:
到這裡為止算是鋪墊,接下來才是重點:假設我們隊類庫進行了升級,同時又希望:
-
使用者程式碼不受影響,除非使用者自己想改。
-
可以自由使用新類庫的功能
-
如果有需要仍然可以使用原來的類庫
解決方法當然是使用內聯名稱空間。首先是對類庫進行處理:
程式碼中為每個版本的類庫定義了名稱空間,同時將最新版本定義為內聯名稱空間。有了這樣的準備之後,使用者程式碼可以是下面這樣:
使用最新類庫的時候,就好像沒有定義過名稱空間一樣;如果實在是需要原來的類庫,可以通用版本字首加類名的方式。
還有一點很重要:由於隱式內聯語法的存在,將來出現ver3的時候,只要將唯一的一個inline關鍵字移動到第一次出現的ver3定義之前就可以了!
作者一句話
內聯名稱空間的應用場景相當有限,但是一旦用上了,還是比較神奇的。
示例程式碼下載地址
https://github.com/xueweiguo/OOThinking/blob/master/20180524%20InlineNamespace.cpp
覺得本文有幫助?請分享給更多人。
閱讀更多更新文章,請掃描下面二維碼,關注微信公眾號【面向物件思考】