C++名稱空間



考慮這樣一種情況:同一個班級裡有兩個名字相同的人,都叫Zara。如果我們需要區分他們,肯定需要使用一些額外的資訊來補充他們的名字,例如他們居住的地區(如果他們住在不同地區),或者他們母親或父親的名字等。

同樣的情況也可能出現在你的C++應用程式中。例如,你可能正在編寫一些程式碼,其中包含一個名為xyz()的函式,並且還有一個可用的庫也包含相同的函式xyz()。現在編譯器無法知道你的程式碼中指的是哪個版本的xyz()函式。

名稱空間的設計就是為了克服這個難題,它被用作額外的資訊來區分在不同庫中具有相同名稱的類似函式、類、變數等。使用名稱空間,你可以定義名稱被定義的上下文。本質上,名稱空間定義了一個作用域。

定義名稱空間

名稱空間定義以關鍵字namespace開頭,後跟名稱空間名稱,如下所示:

namespace namespace_name {
   // code declarations
}

要呼叫函式或變數的啟用名稱空間的版本,請在前面加上名稱空間名稱 (::),如下所示:

name::code;  // code could be variable or function.

讓我們看看名稱空間如何作用於包括變數和函式在內的實體:

#include <iostream>
using namespace std;

// first name space
namespace first_space {
   void func() {
      cout << "Inside first_space" << endl;
   }
}

// second name space
namespace second_space {
   void func() {
      cout << "Inside second_space" << endl;
   }
}

int main () {
   // Calls function from first name space.
   first_space::func();
   
   // Calls function from second name space.
   second_space::func(); 

   return 0;
}

如果我們編譯並執行上面的程式碼,將會產生以下結果:

Inside first_space
Inside second_space

using 指令

你還可以使用using namespace指令避免在名稱空間前新增字首。此指令告訴編譯器後續程式碼正在使用指定名稱空間中的名稱。因此,名稱空間將隱式地應用於後續程式碼:

#include <iostream>
using namespace std;

// first name space
namespace first_space {
   void func() {
      cout << "Inside first_space" << endl;
   }
}

// second name space
namespace second_space {
   void func() {
      cout << "Inside second_space" << endl;
   }
}

using namespace first_space;
int main () {
   // This calls function from first name space.
   func();
   
   return 0;
}

如果我們編譯並執行上面的程式碼,將會產生以下結果:

Inside first_space

‘using’指令也可以用來引用名稱空間中的特定專案。例如,如果你打算使用的std名稱空間的唯一部分是cout,你可以如下引用它:

using std::cout;

後續程式碼可以引用cout而無需新增名稱空間字首,但std名稱空間中的其他專案仍然需要顯式指定,如下所示:

#include <iostream>
using std::cout;

int main () {
   cout << "std::endl is used with std!" << std::endl;
   
   return 0;
}

如果我們編譯並執行上面的程式碼,將會產生以下結果:

std::endl is used with std!

using指令中引入的名稱遵循正常的範圍規則。該名稱從using指令的位置可見,到包含該指令的作用域的末尾。在外層作用域中定義的同名實體將被隱藏。

不連續名稱空間

名稱空間可以分成幾部分定義,因此名稱空間是由其分別定義的部分的總和組成的。名稱空間的不同部分可以分佈在多個檔案中。

因此,如果名稱空間的一部分需要在另一個檔案中定義的名稱,則該名稱仍然必須宣告。編寫以下名稱空間定義,要麼定義一個新的名稱空間,要麼向現有的名稱空間新增新元素:

namespace namespace_name {
   // code declarations
}

巢狀名稱空間

名稱空間可以巢狀,你可以在另一個名稱空間內定義一個名稱空間,如下所示:

namespace namespace_name1 {
   // code declarations
   namespace namespace_name2 {
      // code declarations
   }
}

你可以使用解析運算子訪問巢狀名稱空間的成員,如下所示:

// to access members of namespace_name2
using namespace namespace_name1::namespace_name2;

// to access members of namespace:name1
using namespace namespace_name1;

在上面的語句中,如果你使用namespace_name1,那麼它將使namespace_name2的元素在作用域中可用,如下所示:

#include <iostream>
using namespace std;

// first name space
namespace first_space {
   void func() {
      cout << "Inside first_space" << endl;
   }
   
   // second name space
   namespace second_space {
      void func() {
         cout << "Inside second_space" << endl;
      }
   }
}

using namespace first_space::second_space;
int main () {
   // This calls function from second name space.
   func();
   
   return 0;
}

如果我們編譯並執行上面的程式碼,將會產生以下結果:

Inside second_space
廣告