namespace 用來建立名稱空間,或者開啟既存的名稱空間,因此,若想在其他標頭檔或原始碼位置,往〈簡介名稱空間〉中既有的 bank 名稱空間添加新的定義,只要指定相同名稱就可以了。例如:
namespace bank {
int x;
namespace vip {
class Foo {
...
};
int x;
}
...
}
名稱空間可以形成巢狀,以上例來說,想使用 Foo 類別的話,必須使用 bank::vip::Foo,各個名稱空間中可以定義自身範疇中的名稱,內部名稱空間可以看得到外部名稱空間的名稱,然而外部名稱空間看不到內部定義的名稱,如果內部定義了與外部同名的名稱,那內部中的名稱會遮蔽外部的同名名稱。
如果標頭檔 a.h 定義了名稱空間為 na,而它被 include 到另一名稱空間中:
namespace nb {
#include "a.h"
...
}
那麼 na 會成為 nb 內部的名稱空間,因此定義在 na 中的名稱,必須使用 nb::na 指定範疇來存取。
名稱空間可以 inline,就好比展開在相對應的位置,例如,如果標頭檔 bankv1.h 定義了 inline 名稱空間為 bankv1:
inline namespace bankv1 {
Account {
...
};
...
}
而它被 include 到另一名稱空間中:
namespace bank {
#include "bankv1.h"
...
}
那麼 bank 不會是 bank 的內部名稱空間,而會像是:
namespace bank {
Account {
...
};
...
}
其作用之一就在於,如果哪天定義了 bankv2,定義在 bankv2.h:
inline namespace bankv2 {
Account {
...
};
...
}
那麼原本的 bankv1.h 可以去除 inline:
namespace bankv1 {
Account {
...
};
...
}
若 bank 名稱空間修改為:
namespace bank {
#include "bankv2.h"
#include "bankv1.h"
...
}
那麼程式中使用到 bank::Account 的程式碼,會是 bankv2.h 定義的版本,如果基於相容性,還想繼續使用 bankv1.h 的定義,可以透過 bank::bankv1 指定範疇來存取。
namespace 也可用來為既有的名稱空間取別名,例如,為 bank::vip 取個 vip 的別名:
namespace vip = bank::vip;
名稱空間可以是匿名的,例如,若有個 foo.cpp 實作如下:
namespace {
int x = 10;
}
void foo() {
std::cout << x << std::endl;
}
...
匿名的名稱空間中定義的名稱,具有 static 的生命週期,在第一次使用到的時候被建立,程式結束之後銷毀,因為沒有名稱,只有與匿名空間同檔案、同層次的程式碼,可以直接存取匿名空間中的名稱,以上例來說,foo 與匿名空間都是定義於全域名稱空間,foo 中可以直接存取 x。
然而,如果有另一個 foo2.cpp 也如下定義了 x:
namespace {
int x = 10;
}
void foo2() {
std::cout << x << std::endl;
}
...
因為只有與匿名空間同檔案、同層次的程式碼,可以直接存取匿名空間中的名稱,x 僅在 foo2.cpp 中可見,若同時使用到 foo.cpp、foo2.cpp,編譯時並不會發生錯誤,然而拿掉匿名的 namespace 定義,就會因 x 重複定義而編譯錯誤。
只有與匿名空間同檔案、同層次的程式碼,可以直接存取匿名空間中的名稱,因此如果是以下:
namespace bank {
namespace {
int x = 10;
}
}
x 就只有同檔案、同樣在 bank 名稱空間的程式碼,才可以直接存取 x,若是同檔案、非同一名稱空間的程式碼,必須透過 bank::x 來存取。

