頭文件中盡量少引用命名空間


今天看到一篇文章” 我再也不想在任何頭文件中看到“using namespace xxx;”了 ”,

里面的內容如下:

在這里,我毫不回避地說了這句話。

作為一個開發者/團隊領導者,我經常會去招聘新的項目成員,有時候也幫助其他組的人來面試應聘者。作為應聘流程之一,我經常要求應聘者寫一些代碼,因此我檢查過相當多的代碼。在最近提交的C++代碼中,我注意到一個趨勢,在任何頭文件中,我總是能看到以下代碼:

usingnamespace std;

如果我用我們的代碼檢查系統(在實踐中我十分推薦這個系統)來檢驗代碼,以上那行代碼經常會跟着一句評論“Timo不會這樣寫的”。他們說得很對,我確實不會這么寫。

那么,為什么我說服了很多C++教材(也許並不是什么好事),讓他們認為使用上面那段代碼是非常壞的方式?讓我們先來看看上面那段代碼做了什么。總的來說,它把命名空間“std”以內的所有內容(或者其他由作者用using調用命名空間)無一例外的引入了目前的命名空間中。請注意我說的“所有內容”,並不是一兩個你想用的類\類型\模板。在一段代碼的開頭引入命名空間的原因則是加強程序模塊化,和減少命名沖突。大體上,它允許你可以寫類似下面的那段代碼,並且保證編譯器可以選擇正確的實現:

std::vector<std::string> names; my_cool_reimplementation::vector<our_internal_stuff::string> othernames;

現在,假定我們正在嘗試減少代碼輸入,並且在以上代碼中使用using聲明(或者更糟糕的,兩個命名空間都聲明了),按照如下代碼來實現:

vector<string> names; vector<our_internal_stuff::string> othernames;

如果這段代碼的作者很幸運的話,編譯器會選擇vector的正確實現,或者至少在最初的階段會這么做。但是過了一段時間,你會碰到一些很奇怪的編譯器錯誤。幸運的話,你能找到這些錯誤的原因——我曾經遇到過類似問題,我花費了好幾天才能找到這類問題的原因。該死,它們會浪費你很多的時間,僅僅因為你為了想少打5個字符的代碼。

並且,如果你把using聲明用在了頭文件中,你會讓這類問題更加惡化,因為命名沖突問題早晚都會在一個調用關系非常非常遠的模塊中神不知鬼不覺的出現,而你可能需要查三層調用才可以找到原因所在,一個頭文件包含了另一個直接使用using聲明的頭文件可以導致命名空間被立刻污染掉,任何一個使用命名空間的文件如果使用了std命名空間的內容,都會導致這類問題。

那么,為什么你能在很多教科書中看到它們使用using namespace std?我的理論是,它確實會幫助改善整本書的排版,並且能減少一些視覺的混亂。在一本紙質書中,你只有很有限的空間來寫文字,因此你必須最大限度的利用它,加之書中的代碼例子通常都很簡單。但另一方面,不同的命名空間限定符會帶來了很多視覺混亂,這會讓讀者很難從上下文判斷作者的意圖。當你想在這個時代寫一些有效率的代碼的時候,以上兩點都不完全對,現在的編譯器大多數能每行處理60-80個單詞(你可以試試,這可以的)。因此,不要亂引入命名空間。

如果你非常明確的想在一個頭文件中使用using聲明,應該怎么做?我們有其他途徑可以減少不得不用using聲明的情況——你可以用以下其中一種,或則多種方式的組合。

首先,你只需使用typedef。我會建議你使用這種方法,即使我並不經常遵循我自己的建議,我也認為無論如何這都是一個在實際應用中很好的方法。實際上,使用typedef有兩個好處——他讓一個類型名可讀性增加,如果你選擇了一個很好的名字,它可以讓作者的意圖更加顯而易見。比較一下如下的聲明方式:

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的作用域限制到需要使用它的代碼中,而不是把它放到代碼的公共空間中。你的工程越大,確保模塊化,和最小化不可預料的負面影響就顯得越發重要。

原文:http://www.ituring.com.cn/article/23606?utm_source=tuicool

我再也不想在任何頭文件中看到“using namespace xxx;”了


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM