爲什麼需要命名空間
假設有一段程序模擬了班級點名的場景,且班級裏存在同名學生。這時老師肯定不會直接喊名字,而會在同名的名字上加上某些標誌或特徵以示區別。
而程序是死腦筋的,它只會按照事先的設定按部就班的點名。並不會因爲存在同名學生而應急處理(加個修飾區分等)。
可以這樣粗糙地理解,這裏的老師就是編譯規則,學生就是變量。這種名字衝突的問題,則稱爲命名空間污染問題
1。
對於大型項目而言,一個項目經常需要劃分爲獨立的子模塊再合併。
而大部分人常用的命名是很容易雷同的。
C++
爲我們提供了另一種方法,即命名空間
。
如何使用
以上文的例子,使用命名空間如下:
//老劉寫的
namespace Liu{
int id;
//...
void fun();
}
//老郭寫的
namespace Guo{
int id;
//...
void fun();
}
::
域解析操作符,在 C++
中用來指明要使用的命名空間。
因此在使用的時候則是: Liu::id
、Guo::id
注意:
命名空間可以在全局作用域或其他作用域內部定義,但不能在函數或類內部定義 1 。
命名空間內部不僅可以聲明或定義變量,對於其它能在命名空間以外聲明或定義的名稱,同樣也都能在命名空間內部進行聲明或定義,例如類、函數、typedef
、#define
等都可以出現在命名空間中 2。
Using
在 C++
中我們經常能看到 std
,它其實是標準庫的命名空間。
std::cout << "Hello Word ! " << std::endl;
上述爲一標誌輸出,若在每次使用標準庫時都加上命名空間,則顯得異常繁瑣。
畢竟偷懶是程序員的一大動力。
C++
提供了更簡潔的方式來使用命名空間成員,即 using
。
該指令將告知編譯器,後面的代碼中,缺省的命名空間設置爲 using
指定的命名空間,於是,上面的代碼可以改寫爲:
using namespace std;
cout << "Hello Word ! " << endl;
此外, using
亦可針對某個變量/方法
using namespace Liu::id;
站在編譯和鏈接的角度,代碼中出現的變量名、函數名、類名等都是一種符號。有的符號可以指代一個內存位置,例如變量名、函數名;有的符號僅僅是一個新的名稱,例如 typedef
定義的類型別名 2。
不連續命名空間
與作用域不同,命名空間可以是不連續的。命名空間由它的分離定義部分的總和構成,命名空間是累積的 1。
我們可以在 A文件
中增加 命名空間A
,在 B文件
中同樣使用 命名空間A
,並增加一些內容。
namespace Liu{
int id;
//...
void fun();
}
即以上代碼,既可以是定義新的命名空間,又可以是添加到現有的命名空間中。
值得注意的是:若命名空間中的某個組成部分需要請求定義在另一個文件中的名稱,則仍然需要聲明該名稱 3。
嵌套命名空間
命名空間可以嵌套,您可以在一個命名空間中定義另一個命名空間,如下所示:
namespace namespace_name1 {
// 代碼聲明
namespace namespace_name2 {
// 代碼聲明
}
}
使用如下:
// 訪問 namespace_name2 中的成員
using namespace namespace_name1::namespace_name2;
// 訪問 namespace:name1 中的成員
using namespace namespace_name1;