命名空間

命名空間的作用

命名空間是爲了防止名字衝突提供更加可控的機制。命名空間分割了全局命名空間,其中每一個命名空間是一個作用域。

命名空間的定義

命名空間由三部分組成,分別是namespace、空間名字和一系列由花括號括起來的聲明和定義。只要能出現在全局作用域中的聲明都能置於命名空間中,例如:類、變量(及其初始化操作)、函數(及其定義)、模板和其他命名空間等。

命名空間的定義既可以定義在全局變量的作用域內,也可以定義在其他的命名空間中,但是不能定義在函數或者類的內部。

命名空間的定義可以是不連續的,定義在該命名空間的名字可以被其他命名空間中的其他成員直接訪問,也可以被這些成員內嵌作用域中的任何單位訪問。命名空間可以不連續的特性使我們可以將幾個獨立的接口和實現文件組成一個命名空間:

  1. 命名空間的一部分成員的作用是定義類,以及聲明作爲類接口的函數及對象,則這些成員應該置於頭文件中,這些頭文件將被包含在使用了這些成員的文件中
  2. 命名空間成員的定義部分則置於另外的源文件中

並且命名空間的外部來定義該命名空間的成員,例如:

cplusplus_primer::Sales_data
cplusplus_primer::operator+(const Sales_data& lhs
                            const Sales_data& rhs)
{
    Sales_data ret(lhs);
}

需要注意的是一般不把#include放到命名空間的內部。這樣做了這就意味着把頭文件中的所有的名字定義成該命名空間的成員。

全局命名空間

全局作用域定義的名字就是定義在全局命名空間中,全局命名空間以隱式的方式聲明,並且任何程序中多存在全局命名空間。由於全局命名空間是隱式的,所以並沒有名字,通常是通過以下的方式來實現訪問的:

::number_name

嵌套的命名空間

內層命名空間聲明的名字將會隱藏外層命名空間聲明的同名成員,在嵌套的內層命名空間中定義的名字只有在內層命名空間中有效,外層命名空間要想訪問它必須添加命名空間的前綴符進行限定。

內聯命名空間

與普通的命名空間不同,內聯命名空間的名字可以直接被外層的命名空間直接使用,無需添加該內聯命名空間的名字作爲前綴進行限定。當應用程序的代碼在一次發佈和另一次發佈之間進行了改變時,通常使用這個機制。使用方式如下:

頭文件FifthEd.h

inline namespace FifthEd
{}

namespace FifthEd//inline 關鍵字必須出現在命名空間第一次定義的地方,但是後續打開該命名空間時可以不寫該關鍵字
{
    class Query_base{};
}

頭文件FourthEd.h

namespace FourthEd
{
    class Item_base{};
}

於是在cplusplus的命名空間中可以如下進行定義

namespace cplusplus_primer{
    #include "FourthEd.h"
    #include "FifthEd.h"
}

按照上述的使用方式,如果想獲得FifthEd中的類,可以使用cplusplus_primer::進行限定;如果想獲得FourthEd中的類,可以使用cplusplus_primer::FourthEd::進行限定。

未命名的命名空間

未命名的命名空間指的是namespace後面緊跟這花括號。未命名的命名空間中定義的成員擁有靜態聲明週期,在程序第一次創建之前使用,並且直到程序結束時纔會銷燬。

之所以提出未命名的命名空間的原因是:在早期時C++將變量聲明成static以使其對於整個文件都有效,但是後來在文件中進行靜態聲明的方式已經被C++標準取消了,現在的方式使用未命名的命名空間來取代static。

注意
  1. 一個未命名的命名空間可以在某一個給定的文件中不連續,但是,不可以跨越多個文件。
  2. 每一個文件定義自己的未明名的名字空間,如果兩個文件都有未命名的名字空間,則這兩個命名空間沒有關係。
  3. 不同的兩個文件中的未命名的命名空間中可以定義相同的名字,並且這些名字屬於不同的實體。
  4. 如果一個頭文件定義了一個未命名的命名空間,則包含該頭文件的文件中對應不同的實體。
  5. 未命名的命名空間的名字的作用域與該命名空間所在的作用域相同。

未命名的命名空間也可以嵌套,例如:

namespace local {
    namespace {
        int i;
    }
}
local::i = 42;  // 正確

使用命名空間成員

命名空間別名

別名的聲明方式如下:

namespace cplusplus_primer
{
}

namespace primer = cplusplus_primer;
注意
  1. 必須是在命名空間定義之前就聲明別名。
  2. 一個命名空間可以有好幾個同義詞或者別名,所有的別名都與命名空間原來的名字等價。

using聲明

一個 using 聲明一次只引入一個命名空間成員。using 聲明的作用域從 using 聲明點開始,直到包含 using 聲明的作用域的末尾,名字都是可見的,外部作用域中定義的同名實體被屏蔽。在有效作用域結束之後,就必須使用完整的經過限定的名字。using 聲明可以出現在全局、局部、類的作用域 和 名字空間中。在類作用域中using聲明只能引用基類成員。

using指示

一個 using 聲明一次引入一個特定命名空間的所有成員。using 指示可以出現在全局、局部的作用域 和 名字空間中,不會出現在類的作用域中。與using聲明不同的是,using聲明的名字的作用域與using聲明的語句的作用域一致;using指示將所聲明的命名空間的所有成員提升到同時包含命名空間和using指示的最近作用域。

using聲明、指示和頭文件

如果頭文件中在其頂層作用域中包含using指示或者using聲明,則會將該命名空間中的名字包含到所有包含該名字的文件中。所以通常在函數或者命名空間中使用using指示或者using聲明。

參考鏈接:
C++名字空間/C++命名空間
C++學習之命名空間

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章