分享 C++命名空间的解释
分類: C/C++
使用命名空間的目的是對標識符的名稱進行本地化,以避免命名沖突。在C++中,變量、函數和類都是大量存在的。如果沒有命名空間,這些變量、函數、類的名稱將都存在于全局命名空間中,會導致很多沖突。比如,如果我們在自己的程序中定義了一個函數toupper(),這將重寫標準庫中的toupper()函數,這是因為這兩個函數都是位于全局命名空間中的。命名沖突還會發生在一個程序中使用兩個或者更多的第三方庫的情況中。此時,很有可能,其中一個庫中的名稱和另外一個庫中的名稱是相同的,這樣就沖突了。這種情況會經常發生在類的名稱上。比如,我們在自己的程序中定義了一個Stack類,而我們程序中使用的某個庫中也可能定義了一個同名的類,此時名稱就沖突了。
Namespace 關鍵字的出現就是針對這種問題的。由于這種機制對于聲明于其中的名稱都進行了本地化,就使得相同的名稱可以在不同的上下文中使用,而不會引起名稱的沖突?;蛟S命名空間最大的受益者就是C++中的標準庫了。在命名空間出現之前,整個C++庫都是定義在全局命名空間中的(這當然也是唯一的命名空間)。引入命名空間后,C++庫就被定義到自己的名稱空間中了,稱之為std。這樣就減少了名稱沖突的可能性。我們也可以在自己的程序中創建自己的命名空間,這樣可以對我們認為可能導致沖突的名稱進行本地化。這點在我們創建類或者是函數庫的時候是特別重要的。
命名空間基礎
namespace 關鍵字使得我們可以通過創建作用范圍來對全局命名空間進行分隔。本質上來講,一個命名空間就定義了一個范圍。定義命名空間的基本形式如下:
namespace?名稱{//聲明}
在命名空間中定義的任何東西都局限于該命名空間內。
下面就是一個命名空間的例子,其中對一個實現簡單遞減計數器的類進行了本地化。在該命名空間中定義了計數器類用來實現計數;其中的upperbound和lowerbound用來表示計數器的上界和下界。
演示命名空間
其中的upperbound,lowerbound和類counter都是有命名空間CounterNameSpace定義范圍的組成部分。
在命名空間中聲明的標識符是可以被直接引用的,不需要任何的命名空間的修飾符。例如,在CounterNameSapce命名空間中,run()函數中就可以直接在語句中引用lowerbound:
點擊(此處)折疊或打開
然而,既然命名空間定義了一個范圍,那么我們在命名空間之外就需要使用范圍解析運算符來引用命名空間中的對象。例如,在命名空間CounterNameSpace定義的范圍之外給upperbound賦值為10,就必須這樣寫:
CounterNameSpace::upperbound = 10;
或者在CounterNameSpace定義的范圍之外想要聲明一個counter類的對象就必須這樣寫:
CounterNameSpace::counter obj;
一般來講,在命名空間之外想要訪問命名空間內部的成員需要在成員前面加上命名空間和范圍解析運算符。
下面的程序演示了如何使用CounterNameSpace這個命名空間:
演示命名空間
請注意:counter類以及upperbound和lowerbound的引用都是在前面加上了CounterNameSpace修飾符。但是,一旦聲明了counter類型的對象,就沒有必須在對該對象的任何成員使用這種修飾符了。因此ob1.run()是可以被直接調用的。其中的命名空間是可以被解析的。
相同的空間名稱是可以被多次聲明的,這種聲明向相互補充的。這就使得命名空間可以被分割到幾個文件中甚至是同一個文件的不同地方中。例如:
?????點擊(此處)折疊或打開
其中命名空間NS被分割成兩部分,但是兩部分的內容卻是位于同一命名空間中的。也就是NS。最后一點:命名空間是可以嵌套的。也就是說可以在一個命名空間內部聲明另外的命名空間。
using關鍵字
如果在程序中需要多次引用某個命名空間的成員,那么按照之前的說法,我們每次都要使用范圍解析符來指定該命名空間,這是一件很麻煩的事情。為了解決這個問題,人們引入了using關鍵字。using語句通常有兩種使用方式:
using namespace?命名空間名稱;
using?命名空間名稱::成員;
第一種形式中的命名空間名稱就是我們要訪問的命名空間。該命名空間中的所有成員都會被引入到當前范圍中。也就是說,他們都變成當前命名空間的一部分了,使用的時候不再需要使用范圍限定符了。第二種形式只是讓指定的命名空間中的指定成員在當前范圍中變為可見。我們用前面的CounterNameSpace來舉例,下面的using語句和賦值語句都是有效的:
using CounterNameSpace::lowerbound; //只有lowerbound當前是可見的
lowerbound = 10; //這樣寫是合法的,因為lowerbound成員當前是可見的
using CounterNameSpace; //所有CounterNameSpace空間的成員當前都是可見的
upperbound = 100; //這樣寫是合法的,因為所有的CounterNameSpace成員目前都是可見的
下面是我們對之前的程序進行修改的結果:
使用using
我們可以使用這種沒有名稱的命名空間創建只有在聲明他的文件中才可見的標識符。也即是說,只有在聲明這個命名空間的文件中,它的成員才是可見的,它的成員才是可以被直接使用的,不需要命名空間名稱來修飾。對于其他文件,該命名空間是不可見的。我們在前面曾經提到過,把全局名稱的作用域限制在聲明他的文件的一種方式就是把它聲明為靜態的。盡管C++是支持靜態全局聲明的,但是更好的方式就是使用這里的未命名的命名空間。
std命名空間
標準C++把自己的整個庫定義在std命名空間中。這就是本書的大部分程序都有下面代碼的原因:
using namespace std;
這樣寫是為了把std命名空間的成員都引入到當前的命名空間中,以便我們可以直接使用其中的函數和類,而不用每次都寫上std::。
當然,我們是可以顯示地在每次使用其中成員的時候都指定std::,只要我們喜歡。例如,我們可以顯示地采用如下語句指定cout:
std::cout << “顯示使用std::來指定cout”;
如果我們的程序中只是少量地使用了 std 命名空間中的成員,或者是引入 std 命名空間可能導致命名空間的沖突的話,我們就沒有必要使用 using namespace std; 了。然而,如果在程序中我們要多次使用 std 命名空間的成員,則采用 using namespace std; 的方式把 std 命名空間的成員都引入到當前命名空間中會顯得方便很多,而不用每次都單獨在使用的時候顯示指定轉載地址:http://blog.renren.com/share/730973714/7874424429
與50位技術專家面對面20年技術見證,附贈技術全景圖
總結
以上是生活随笔為你收集整理的分享 C++命名空间的解释的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 带你走进和声搜索算法(Harmony s
- 下一篇: 德国80%的统计学教授都会答错的6个与P