2010-12-22 53 views
16

我一直在長時間使用static關鍵字來定義內部鏈接。後來,我轉向使用匿名命名空間封裝本地事物的C++風格。匿名命名空間:他們真的很棒嗎?

但是,現在當我使用匿名命名空間多年的時候,我開始認爲static關鍵字更易於使用!

一個常見的問題是,我有這樣的模式:

namespace { 
    // ...five pages of code... 
} // namespace 

要查看某個函數內部或外部的聯繫,我現在必須滾動了很多,而不是舊的C風格,我可以檢查前面的功能/對象是否有static

我知道有一些事情匿名命名空間可以做到這一點static不能隱藏typedefs - 但個人而言,我並不是真的對此非常感興趣。

你對此有何看法?匿名命名空間的勝利是否值得降低可讀性?或者我都出錯了?

+3

命名空間範圍內的`static`函數已被棄用,這是不使用它們的充分理由。 anon命名空間中的函數具有`static`的所有優點,除了它們具有外部鏈接。後者我認爲已經由編譯器處理,從導出的部分中刪除匿名命名空間中定義的名稱。 – 2010-12-22 21:58:04

+11

@實際上,靜態函數永遠不會被棄用。棄用僅針對* objects *。但是,在n3225中已經取消了棄用:在C++ 0x中,不再推薦使用它來爲對象或函數提供內部鏈接。另一個區別是未命名的名稱空間會保留外部鏈接:未命名的名稱空間及其內容將在C++ 0x中獲得內部鏈接。所以在static-way和namespace-way之間似乎沒有任何區別,除了namespace-way將允許諸如`namespace {int a; } int a;`。 – 2010-12-22 22:09:27

回答

20

如果您的命名空間中的代碼太長,沒有什麼可以阻止你這樣做:

namespace { 
    int foo(char* x) { 
     return x[0] + x[1]; 
    } 
} 

namespace { 
    int bar(char *x, char *y) { 
     return foo(x) + foo(y); 
    } 
} 

在C++ 03使用具名命名空間的實用優點恰恰是內容有外部聯動(但在TU外部仍然不可見,因爲沒有辦法參照它們)。模板參數不能有內部鏈接:

namespace { 
    int foo(const char* x) { 
     return x[0] + x[1]; 
    } 
} 

static int foo2(const char *x) { 
    return x[0] + x[1]; 
} 

template <int (*F)(const char*)> 
void baz(const char *p) { 
    F(p); 
} 

int main() { 
    baz<foo>("ab"); // OK 
    baz<foo2>("ab"); // not valid 
} 
1

一位不願具名的命名空間是不會讓一個類聲明污染在全球範圍內的唯一的事。在.cpp文件中定義類時非常有用。

2

除了由史蒂夫注意到了非常有效的點我看在匿名的命名空間,使他們優於靜態功能等非常重要的方面: 局部性,易於重構和信息隱藏

假設您有一個或兩個類函數,它們需要幾個其他非常具體的輔助函數,但不使用類成員。如果你堅持使用Robert C. Martin(函數應該很小並且服務於一個明確定義的目的),你會經常發現大的函數可以被重構爲較小的函數,儘管這些較小的函數在開始時可能只用於前一個大函數。

那麼選擇你有:

  1. 立即作出了新的(也許是私有)類:

    這需要相當大量的輸入可能是矯枉過正和-lets面對它 - 每個人 有時是懶惰或匆忙。

  2. 生成私有靜態函數和非成員函數:

    兩個需要編輯的頭文件和CPP文件,如果你這樣做 正常,所以還是有點負擔可能中斷您的 工作流程更並且生成不必要的代碼 混亂您的頭文件,可能需要前向聲明或 甚至在您的頭文件中包含更多內容。

  3. 匿名命名空間:

    你不需要 成員訪問,並提供一個目的的輔助功能 - >把它放在那裏,靠近寫這個 功能類的方法,其中將使用它。這是由我的首選大 :它很快,它不會混亂頭文件。這個命名空間清楚地表明:除了這個cpp以外,這個命令不會被其他任何東西使用。沒有 的朋友會使用它,並且沒有圖書館用戶會知道它的存在。你幾乎不會更明顯,通常這種範例會導致更清潔的功能設計,這是很少的輸入參數,只有一個 輸出被修改。此外,您還有功能位置:定義在主要使用 之前。雖然這可能是一個缺點,但我發現在瀏覽大類的 實現時非常有幫助。另一個優點是跨越幾個 函數的常量,但對圖書館用戶來說並不是很有趣。將它們放在 命名空間中,最好與使用它們的函數相同。如果後來變爲 ,則需要常量和其他函數,將整個變換爲一個類,它已經整齊地打包了。

聲明:許多人可能會爭辯說,使用pimpl是遠遠更清潔。這只是我個人的意見。

相關問題