C++命名空間

 

使用命名空間的目的是對標識符的名稱進行本地化,以免命名衝突。在C++中,變量、函數和類都是大量存在的。若是沒有命名空間,這些變量、函數、類的名稱將都存在於全局命名空間中,會致使不少衝突。好比,若是咱們在本身的程序中定義了一個函數toupper(),這將重寫標準庫中的toupper()函 數,這是由於這兩個函數都是位於全局命名空間中的。命名衝突還會發生在一個程序中使用兩個或者更多的第三方庫的狀況中。此時,頗有可能,其中一個庫中的名 稱和另一個庫中的名稱是相同的,這樣就衝突了。這種狀況會常常發生在類的名稱上。好比,咱們在本身的程序中定義了一個Stack類,而咱們程序中使用的某個庫中也可能定義了一個同名的類,此時名稱就衝突了。css

Namespace 關鍵字的出現就是針對這種問題的。因爲這種機制對於聲明於其中的名稱都進行了本地化,就使得相同的名稱能夠在不一樣的上下文中使用,而不會引發名稱的衝突。或許命名空間最大的受益者就是C++中的標準庫了。在命名空間出現以前,整個C++庫都是定義在全局命名空間中的(這固然也是惟一的命名空間)。引入命名空間後,C++庫就被定義到本身的名稱空間中了,稱之爲std。這樣就減小了名稱衝突的可能性。咱們也能夠在本身的程序中建立本身的命名空間,這樣能夠對咱們認爲可能致使衝突的名稱進行本地化。這點在咱們建立類或者是函數庫的時候是特別重要的。ios

命名空間基礎函數

namespace 關鍵字使得咱們能夠經過建立做用範圍來對全局命名空間進行分隔。本質上來說,一個命名空間就定義了一個範圍。定義命名空間的基本形式以下:spa

namespace 名稱{//聲明}code

在命名空間中定義的任何東西都侷限於該命名空間內。對象

下面就是一個命名空間的例子,其中對一個實現簡單遞減計數器的類進行了本地化。在該命名空間中定義了計數器類用來實現計數;其中的upperbound和lowerbound用來表示計數器的上界和下界。blog

演示命名空間it

namespace CounterNameSpace
{
    int upperbound;
    int lowerbound;
    class counter
    {
        int count;
   public:
     counter(int n)
     {
            if ( n <= upperbound ){
                count = n;
            } else  {
                count = upperbound;
            }
      }
    void reset(int n)
     {
       if ( n < upperbound )
            {
                count = n;
            }
        }
     int run() {
      if ( count > lowerbound)
       {
                return count--;
       } else {
                return lowerbound;
       }
      }
    };
}

 

其中的upperbound,lowerbound和類counter都是有命名空間CounterNameSpace定義範圍的組成部分。io

在命名空間中聲明的標識符是能夠被直接引用的,不須要任何的命名空間的修飾符。例如,在CounterNameSapce命名空間中,run()函數中就能夠直接在語句中引用lowerbound:class

if ( count > lowerbound)
{
return count--;
}

然而,既然命名空間定義了一個範圍,那麼咱們在命名空間以外就須要使用範圍解析運算符來引用命名空間中的對象。例如,在命名空間CounterNameSpace定義的範圍以外給upperbound賦值爲10,就必須這樣寫:

CounterNameSpace::upperbound = 10;

或者在CounterNameSpace定義的範圍以外想要聲明一個counter類的對象就必須這樣寫:

CounterNameSpace::counter obj;

通常來說,在命名空間以外想要訪問命名空間內部的成員須要在成員前面加上命名空間和範圍解析運算符。

下面的程序演示瞭如何使用CounterNameSpace這個命名空間:

#include <iostream>
using namespace std;
namespace CounterNameSpace
{
    int upperbound;
    int lowerbound;
    class counter
    {
        int count;
    public:
        counter(int n)
        {
            if ( n <= upperbound )
            {
                count = n;
            } else
            {
                count = upperbound;
            }
        }
        void reset(int n)
        {
            if ( n < upperbound )
            {
                count = n;
            }
        }
        int run()
        {
          if ( count > lowerbound)
            {
                return count--;
            }
            else
                return lowerbound;
        }
    };
}
int main()
{
 CounterNameSpace::upperbound = 100;
 CounterNameSpace::lowerbound = 0;
 CounterNameSpace::counter ob1(10);
  int i;
  do {
   i = ob1.run();        
   cout << i << " ";
 } while (i > CounterNameSpace::lowerbound);
 cout << endl;
 CounterNameSpace::counter ob2(20);
do {
    i = ob2.run();
    cout << i << " ";
    } while (i > CounterNameSpace::lowerbound);
    cout << endl;
    ob2.reset(100);
    do
    {  i = ob2.run();
        cout << i << " ";
    } while (i > CounterNameSpace::lowerbound);
    cout << endl;
    return 0;
}

請注意:counter類以及upperbound和lowerbound的引用都是在前面加上了CounterNameSpace修飾符。可是,一旦聲明瞭counter類型的對象,就沒有必須在對該對象的任何成員使用這種修飾符了。所以ob1.run()是能夠被直接調用的。其中的命名空間是能夠被解析的。

相同的空間名稱是能夠被屢次聲明的,這種聲明向相互補充的。這就使得命名空間能夠被分割到幾個文件中甚至是同一個文件的不一樣地方中。例如:

  1. namespace NS
    {
    int i;
    }
     
    //...
    namespace NS
    {
        int j;
    }

    其中命名空間NS被分割成兩部分,可是兩部分的內容倒是位於同一命名空間中的。也就是NS。最後一點:命名空間是能夠嵌套的。也就是說能夠在一個命名空間內部聲明另外的命名空間。

using關鍵字

若是在程序中須要屢次引用某個命名空間的成員,那麼按照以前的說法,咱們每次都要使用範圍解析符來指定該命名空間,這是一件很麻煩的事情。爲了解決這個問題,人們引入了using關鍵字。using語句一般有兩種使用方式:

using namespace 命名空間名稱;

using 命名空間名稱::成員;

第一種形式中的命名空間名稱就是咱們要訪問的命名空間。該命名空間中的全部成員都會被引入到當前範圍中。也就是說,他們都變成當前命名空間的一部分了,使用的時候再也不須要使用範圍限定符了。第二種形式只是讓指定的命名空間中的指定成員在當前範圍中變爲可見。咱們用前面的CounterNameSpace來舉例,下面的using語句和賦值語句都是有效的:

using CounterNameSpace::lowerbound; //只有lowerbound當前是可見的

lowerbound = 10; //這樣寫是合法的,由於lowerbound成員當前是可見的

using CounterNameSpace; //全部CounterNameSpace空間的成員當前都是可見的

upperbound = 100; //這樣寫是合法的,由於全部的CounterNameSpace成員目前都是可見的

下面是咱們對以前的程序進行修改的結果:

使用using

#include <iostream>
 
using namespace std;
 
namespace CounterNameSpace
{
    int upperbound;
    int lowerbound;
    class counter
    {
        int count;
    public:
        counter(int n)
        {
            if ( n < upperbound)
            {
                count = n;
            }
            else
            {
                count = upperbound;
            }
        }
 
        void reset( int n )
        {
            if ( n <= upperbound )
            {
                count = n;
            }
        }
 
        int run()
        {
            if ( count > lowerbound )
            {
                return count--;
            }
            else
            {
                return lowerbound;
            }
        }
    }; 
}
int main()
{
    //這裏只是用CounterNameSpace中的upperbound
    using CounterNameSpace::upperbound;
 
    //此時對upperbound的訪問就不須要使用範圍限定符了
    upperbound = 100;
    //可是使用lowerbound的時候,仍是須要使用範圍限定符的
    CounterNameSpace::lowerbound = 0;
    CounterNameSpace::counter ob1(10);
    int i;
 
    do
    {
        i = ob1.run();
        cout << i << " ";
    }while( i > CounterNameSpace::lowerbound);
    cout << endl;
 
    //下面咱們將使用整個CounterNameSpace的命名空間
    using namespace CounterNameSpace;
    counter ob2(20);
    do
    {
        i = ob2.run();
        cout << i << " ";
    }while( i > CounterNameSpace::lowerbound);
    cout << endl;
 
    ob2.reset(100);
    lowerbound = 90;
    do
    {
        i = ob2.run();
        cout << i << " ";
    }while( i > lowerbound);
 
    return 0;
}
上面的程序還爲咱們演示了重要的一點:當咱們用using引入一個命名空間的時候,若是以前有引用過別的命名空間(或者同一個命名空間),則不會覆蓋掉對以前的引入,而是對以前引入內容的補充。也就是說,到最後,上述程序中的std和CounterNameSpace這兩個命名空間都變成全局空間了。

有一種特殊的命名空間,叫作未命名的命名空間。這種沒有名稱的命名空間使得咱們能夠建立在一個文件範圍裏可用的命名空間。其通常形式以下:
namespace
{
  //內容
}

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
相關文章
相關標籤/搜索