對于C++編譯器,那些名字可見至關重要,太多的名字可見将導緻名字查找效率的降低,而名字太少将導緻無法找到所需類型或函數的名字,進而導緻編譯錯誤。除了最常用的include可以導入可見名字之外,using關鍵字也可以導入名字到特定的編譯單元中(單個cpp檔案)。
差別:
Using聲明: usingnamespace std; -- 導入某個名字空間可見的名字實體
Using指令: using N::Widget; -- 導入特定名字
Using用于導入特定名字空間下的名字實體,可以是全部名字實體(usingnamespace std;),也可以是特定的名字實體(using std::map;)。
工作原理:using聲明将擷取的是在遇到using聲明瞬間所見到的名字空間中的實體。這點是可以了解的,這樣的工作方式有利于避免名字沖突(過多導緻污染),加快名字查找過程。但這同時意味着:隻有在using namespace std;語句之前所include的std頭檔案的名字實體被引入,即using并未引入所有來自std的名字實體。
Using關鍵字定理:絕對不要在include之前使用using聲明或指令。
推論:不要在頭檔案中使用using聲明或指令,相反應該使用名字空間限定所有的名字,尤其是來自其他名字空間的名字。(原因:1)頭檔案并不知道完全的include資訊,頭檔案總是被用于其他cpp中,其後總會出現另外的include; 2)避免不必要的名字污染)
例子:
// snippet 1
namespace A {
int f(double);
}
// snippet 2
namespace B {
using A::f;
void g();
// snippet 3
int f(int);
// snippet 4
void B::g() {
f(1); // which overload iscalled?
這幾個檔案先後出現順序将決定f(1)是否可編譯(所有的f函數定義均不可見)?以及重載哪個函數(哪些函數可見,并參與重載)。
錯誤地使用using将導緻名字空間污染,或錯誤地導入不完整的名字空間的瞬間快照(導緻無法找到特定名字實體)。在頭檔案中,使用using将使這個問題更加嚴重(多處使用,使用順序不可控)。
例外:編寫類成員級的using聲明導入所需的基類成員名字是一個合法技巧,隻有這樣才能避免基類的名字被屏蔽,如重載函數不可見問題。(見派生類的函數重載)
----------------------------------------------------
本文轉自 zhenjing 部落格園部落格,原文連結:http://www.cnblogs.com/zhenjing/archive/2010/11/04/1868891.html ,如需轉載請自行聯系原作者