C的開發人員會經常使用#define,即用宏來聲明常量,但宏卻是全域的,對大的工程很難維護,經常是導致名字衝突。還好,C++給我們帶來了namespace名字空間。它的使用如下,名字空間可以把一組邏輯分組,同時名字空間也是一種範圍。
view plain
copy to clipboard
print
?
- namespace
outspname
- {
- const
int
CVAR1 = 1;
- const
char
*
const
CVAR2 =
"33333"
;
- void
test();
-
- namespace
inspname
- {
- enum
{ A, B, C};
- class
Klass
- {
- };
- }
- }
namespace outspname<br />{<br /> const int CVAR1 = 1;<br /> const char* const CVAR2 = "33333";<br /> void test();</p><p> namespace inspname<br /> {<br /> enum { A, B, C};<br /> class Klass<br /> {<br /> };<br /> }<br />}
但即使一個簡單的名字空間,其中也有不少的玄機。
1.當某個名字在自己的空間之外使用,在反覆地在前面加上名字空間作為限定詞, 如
view plain
copy to clipboard
print
?
- const
int
local = outspname::inspname::A
const int local = outspname::inspname::A
這樣寫是不是很令人煩。在某個小的局部範圍內,
我們可以通過一個使用聲明。如
view plain
copy to clipboard
print
?
- {
- using
outspname::inspname::A;
- const
int
local = A;
- }
{<br /> using outspname::inspname::A;<br /> const int local = A;<br />}
2.還有,我們也可以通過一個使用指令把該名字空間下所有的名字變成可用。如下所示,與第一點的用法區別,是using 後面有個namespace。同樣只在轉換時,或者在一個小的局部範圍內使用using namesapce,否則也會帶來名字的汙染。
view plain
copy to clipboard
print
?
- {
- using
namespace
outspname;
- const
int
local2 = CVAR1;
- const
int
local2 = inspname::B;
- {
- using
namespace
inspname;
- Klass* p = new
Klass();
- }
-
- }
{<br /> using namespace outspname;<br /> const int local2 = CVAR1;<br /> const int local2 = inspname::B;<br /> {<br /> using namespace inspname;<br /> Klass* p = new Klass();<br /> }</p><p>}
但使用using namespace這種用法時,要注意下面一點,如在某個.h中聲明了有testname::test的方法。
view plain
copy to clipboard
print
?
- namespace
testname
- {
- void
test(
int
param);
- }
namespace testname<br />{<br /> void test(int param);<br />}
在其.cpp中,不能使用如下這種方式,test方法只是此編譯單元的一個局部方法,並非testname名字空間的test方法實現。
view plain
copy to clipboard
print
?
- using
testname;
- void
test(
int
param)
- {
- }
using testname;<br />void test(int param)<br />{<br />}
正確的使用方式是
view plain
copy to clipboard
print
?
- namespace
testname
- {
- void
test(
int
param)
- {
- }
- }
namespace testname<br />{<br /> void test(int param)<br /> {<br /> }<br />}
或者是
view plain
copy to clipboard
print
?
- void
testname::test(
int
param)
- {
- }
void testname::test(int param)<br />{<br />}
3.名字空間的別名,當名字空間很長或嵌套很深時,我們可以使用名字空間別名,用法如下:
view plain
copy to clipboard
print
?
- namespace
oin = outspname::inspname;
namespace oin = outspname::inspname;
4.無名名字空間,無名名字空間主要是保持代碼的局部性,使用如下:
view plain
copy to clipboard
print
?
- namespace
- {
- const
int
CVAR1 = 1;
- void
test();
- }
namespace<br />{<br /> const int CVAR1 = 1;<br /> void test();<br />}
但一定要注意的一點是,在C++編譯器實現時,無名名字空間其實是有名字的,這個隱含的名字跟它所在編譯單元名字相關。
所以基於這一點,我們不能跨編譯單元使用無名名字空間中的名字。
上面的聲明等價於
view plain
copy to clipboard
print
?
- namespace
$$$
- {
- const
int
CVAR1 = 1;
- void
test();
- }
- using
namespace
$$$;
namespace $$$<br />{<br /> const int CVAR1 = 1;<br /> void test();<br />}<br />using namespace $$$;
其中$$$在其所在的範圍裡具有惟一性的名字,每個編譯單元裡的無名名字空間也是互不相同的,using namesapce $$$只是當前的編譯單元的隱含名字,所以不能跨編譯單元使用無名名字空間中的名字。
假設上面的test方法在是a.h與a.cpp中定義與實現的,但在b.h或b.cpp中就不能直接使用test方法或CVAR1。因為在b的這個編譯單元中連結的是b這個編譯單元中的test符號,並非a編譯單元中的test符號,也就會出現未定符號。
5.要避免名字空間使用很短的名字,也不能太長,更不能嵌套太深了,個人覺得不要超過4層。
轉載註明出處:http://blog.csdn.net/szlanny/archive/2009/07/12/4341531.aspx