做爲一個開發者/團隊領導者,我常常會去招聘新的項目成員,有時候也幫助其餘組的人來面試應聘者。做爲應聘流程之一,我常常要求應聘者寫一些代碼,所以我檢查過至關多的代碼。在最近提交的C++代碼中,我注意到一個趨勢,在任何頭文件中,我老是能看到如下代碼:面試
usingnamespace std;
若是我用咱們的代碼檢查系統(在實踐中我十分推薦這個系統)來檢驗代碼,以上那行代碼常常會跟着一句評論「Timo不會這樣寫的」。他們說得很對,我確實不會這麼寫。模塊化
那麼,爲何我說服了不少C++教材(也許並非什麼好事),讓他們認爲使用上面那段代碼是很是壞的方式?讓咱們先來看看上面那段代碼作了什麼。總的來講,它把命名空間「std」之內的全部內容(或者其餘由做者用using調用命名空間)無一例外的引入了目前的命名空間中。請注意我說的「全部內容」,並非一兩個你想用的類\類型\模板。在一段代碼的開頭引入命名空間的緣由則是增強程序模塊化,和減小命名衝突。大致上,它容許你能夠寫相似下面的那段代碼,而且保證編譯器能夠選擇正確的實現:函數
std::vector<std::string> names; my_cool_reimplementation::vector<our_internal_stuff::string> othernames;
如今,假定咱們正在嘗試減小代碼輸入,而且在以上代碼中使用using聲明(或者更糟糕的,兩個命名空間都聲明瞭),按照以下代碼來實現:spa
vector<string> names; vector<our_internal_stuff::string> othernames;
若是這段代碼的做者很幸運的話,編譯器會選擇vector的正確實現,或者至少在最初的階段會這麼作。可是過了一段時間,你會碰到一些很奇怪的編譯器錯誤。幸運的話,你能找到這些錯誤的緣由——我曾經遇到過相似問題,我花費了好幾天才能找到這類問題的緣由。該死,它們會浪費你不少的時間,僅僅由於你爲了想少打5個字符的代碼。code
而且,若是你把using聲明用在了頭文件中,你會讓這類問題更加惡化,由於命名衝突問題遲早都會在一個調用關係很是很是遠的模塊中神不知鬼不覺的出現,而你可能須要查三層調用才能夠找到緣由所在,一個頭文件包含了另外一個直接使用using聲明的頭文件能夠致使命名空間被馬上污染掉,任何一個使用命名空間的文件若是使用了std命名空間的內容,都會致使這類問題。ip
那麼,爲何你能在不少教科書中看到它們使用using namespace std?個人理論是,它確實會幫助改善整本書的排版,而且能減小一些視覺的混亂。在一本紙質書中,你只有頗有限的空間來寫文字,所以你必須最大限度的利用它,加之書中的代碼例子一般都很簡單。但另外一方面,不一樣的命名空間限定符會帶來了不少視覺混亂,這會讓讀者很難從上下文判斷做者的意圖。當你想在這個時代寫一些有效率的代碼的時候,以上兩點都不徹底對,如今的編譯器大多數能每行處理60-80個單詞(你能夠試試,這能夠的)。所以,不要亂引入命名空間。作用域
若是你很是明確的想在一個頭文件中使用using聲明,應該怎麼作?咱們有其餘途徑能夠減小不得不用using聲明的狀況——你能夠用如下其中一種,或則多種方式的組合。開發
首先,你只需使用typedef。我會建議你使用這種方法,即便我並不常常遵循我本身的建議,我也認爲不管如何這都是一個在實際應用中很好的方法。實際上,使用typedef有兩個好處——他讓一個類型名可讀性增長,若是你選擇了一個很好的名字,它可讓做者的意圖更加顯而易見。比較一下以下的聲明方式:get
std::map<std::string,long> clientLocations;
typedef std::map<std::string,long>ClientNameToZip;
ClientNameToZip clientLocations;
第二個聲明——即便它被展開爲兩行——也比第一個聲明更加直觀,同時,它也避免了命名空間模糊化。編譯器
另一個選擇則是用兩種方法來限制using聲明的做用域——僅僅是你想用的那個「using」符號,例如:
using std::string;
可是,把這段聲明扔到頭文件中,幾乎和使用「using namespace」同樣糟糕,所以,你應該使用做用域來限制下它的可見性,來確保你的using聲明真的只在第一次作using聲明的地方有效。例如,你能夠用以下方法限制類聲明做用域:
namespace bar {
struct zzz {…};
}
class foo {
usingnamespace bar; zzz m_snooze;// Pulls in bar::zzz
};
或者,你能夠直接把using的做用域限制到一個函數中,例如:
void temp()
{
usingnamespace std;
string test ="fooBar";
}
無論哪一種方法,你均可以把using的做用域限制到須要使用它的代碼中,而不是把它放到代碼的公共空間中。你的工程越大,確保模塊化,和最小化不可預料的負面影響就顯得愈加重要。
原文:I don’t want to see another 「using namespace xxx;」 in a header file ever again