1、命名空間能夠劃分全域命名空間。一個命名空間是一個範圍。
2、命名空間可以在全域範圍或其它範圍內部定義,但不能在函數或類內部定義。可以在命名空間中放入可以出現在全域範圍的任意聲明。
3、命名空間範圍不能以分號結束。
4、命名空間是累積的。一個命名空間的分離部分可以分散在多個檔案中。
樣本
namespace namespace_name{}
既可以定義新的命名空間,也可以添加到現存命名空間中。
5、命名空間定義可以不連續意味著,可以用分離的介面檔案和實現檔案構成命名空間。因此,可以用與管理自己的類和函數定義相同的方法來組織命名空間。
樣本
namespace cplusplus_primer {class Sales_item { /* ... */};Sales_item operator+(const Sales_item&,const Sales_item&);// declarations for remaining functions in the Sales_iteminterface}// ---- Query.h ----namespace cplusplus_primer {class Query {public:Query(const std::string&);std::ostream &display(std::ostream&) const;// ...};class Query_base { /* ... */};}// ---- Sales_item.cc ----#include "Sales_item.h"namespace cplusplus_primer {// definitions for Sales_item members and overloaded operators}// ---- Query.cc ----#include "Query.h"namespace cplusplus_primer {// definitions for Query members and related functions}
也可以在命名空間定義的外部定義命名空間成員,用類似於在類外定義類成員的方法。
6、定義在全域範圍的名字(在任意類、函數或命名空間外部聲明的名字)是定義在全域命名空間的。全域命名空間是隱式聲明的,沒有名字,通過::mem_name引用全域命名空間的成員。
7、未命名的命名空間的定義局部於特定檔案,可以在給定檔案中不連續,從不跨越多個文字檔。每個檔案都有自己的未命名的命名空間。
未命名的命名空間中定義的名字可以在定義該命名空間的在的範圍中找到。
如果標頭檔定義了未命名的命名空間,那麼,在每個包含該標頭檔的檔案中,該命名空間中的名字將定義不同的局部實體。
因該避免檔案靜態而使用未命名的命名空間代替。
8、除了在函數或其他範圍內部,標頭檔不應該包含using批示或using聲明。
9、命名空間別名:
一個命名空間可以有許多別名,所有別名以及原來的命名空間都可以互換使用。
樣本
namespace primer = cplusplus_primer;
10、using指示與using聲明
樣本
namespace namespace_myname{int i;}using namespace namespace_myname; //using directiveusing namespace_myname::i; //using declaration
由using聲明引起的二義性錯誤在聲明點而不是使用點檢測,因此更容易發現和修正。
11、實參相關的尋找與類類型形參
樣本
std::string s;//ok: calls std::getline(std::istream&, const std::string&)getline(std::cin, s);
接受類類型形參(或類類型指標及引用形參)的函數(包括重載操作符),以及與類本身定義在同一命名空間中的函數(包括重載操作符),在類類型對象(或類類型的引用及指標)作為實參的時候是可見的。
當編譯器看到 getline 函數的使用getline(std::cin, s);的時候,它在當前範圍,包含調用的範圍以及定義 cin 的類型和string 類型的命名空間中尋找匹配的函數。因此,它在命名空間 std 中尋找並找到由 string 類型定義的 getline 函數。
12、有一個或多個類類型形參的函數的名字尋找包括每個形參類型的命名空間。
13、重載與using directive,declaration
1)重載與using聲明
樣本
using NS::print(int); // error: cannot specify parameter listusing NS::print; // ok: using declarations specify names only
如果命名空間內部的函數是重載的,那麼該函數名字的using聲明聲明了所有具有該函數名字的函數。
2)重載與using指示
如果命名空間函數與命名空間所在的範圍中聲明的函數同名,就將命名空間成員加到重載集合中。
樣本
namespace libs_R_us {extern void print(int);extern void print(double);}void print(const std::string &);// using directive:using namespace libs_R_us;// using directive added names to the candidate set for calls to print:// print(int) from libs_R_us// print(double) from libs_R_us// print(const std::string &) declared explicitlyvoid fooBar(int ival){print("Value: "); // calls global print(const string &)print(ival); // calls libs_R_us::print(int)}
14、命名空間與模板
模板的顯式特化必須在定義通用模板的命名空間中聲明,否則,該特化將與它所特化的模板不同名。
有兩種定義特化的方式:一種是重新開啟命名空間並加入特化的定義(命名空間定義是不連續);或者,可以用與在命名空間定義外部定義命名空間成員相同的方式來定義特化:使用由命名空間名字限定的模板名定義特化。
為了提供命名空間中所定義模板的自己的特化,必須保證在包含原始模板定義的命名空間中定義特化。