2009-04-17 67 views
148

東西,我發現自己經常做的最近被宣佈類型定義相關的是類中的某一類,即C++中的內部typedefs - 風格好還是風格不好?

class Lorem 
{ 
    typedef boost::shared_ptr<Lorem> ptr; 
    typedef std::vector<Lorem::ptr> vector; 

// 
// ... 
// 
}; 

這些類型然後在代碼的其他地方使用:

Lorem::vector lorems; 
Lorem::ptr lorem(new Lorem()); 

lorems.push_back(lorem); 

的原因,我喜歡它:

  • 它減少了由類模板引入的噪音,std::vector<Lorem>變成Lorem::vector
  • 它用作意圖聲明 - 在上面的示例中,Lorem類旨在通過boost::shared_ptr進行引用計數並存儲在向量中。
  • 它允許實現更改 - 即,如果需要更改Lorem以在後續階段侵入引用計數(通過boost::intrusive_ptr),那麼這會對代碼產生最小的影響。
  • 我認爲它看起來'漂亮',可以說更容易閱讀。

的原因,我不喜歡它:

  • 有時對於依賴關係問題 - 如果你要嵌入,比方說,另一個類而只需要內Lorem::vector(或希望)轉發聲明Lorem(而不是引入對它的頭文件的依賴),那麼你最終不得不使用顯式類型(例如boost::shared_ptr<Lorem>而不是Lorem::ptr),這有點不一致。
  • 它可能不是很常見,因此難以理解?

我試着用我的編碼風格來客觀,所以最好能對它有一些其他的看法,這樣我就可以剖析我的想法了。

回答

131

我認爲這是優秀的風格,我自己使用它。儘可能限制名稱範圍總是最好的,並且類的使用是在C++中執行此操作的最佳方式。例如,C++標準庫大量使用類中的typedef。

+0

這是一個很好的觀點,我不知道它看起來'漂亮'是我的潛意識細微地指出範圍有限是一件好事。不過,我想知道STL在課堂模板中主要使用它的事實是否會使其具有細微差別?在「具體」課堂中辯解更難嗎? – 2009-04-17 08:55:11

+1

那麼標準庫是由模板而不是類組成的,但我認爲兩者的理由是相同的。 – 2009-04-17 09:38:03

2

我建議將這些類型定義移到類之外。這樣,您可以刪除對共享指針和向量類的直接依賴關係,只有在需要時纔可以包含它們。除非您在類實現中使用這些類型,否則我認爲它們不應該是內部類型定義。

您喜歡它的原因仍然匹配,因爲它們是通過typedef類型別名解決的,而不是通過在類中聲明它們。

+0

這會使用typedefs監聽匿名命名空間嗎?! typedef的問題是它隱藏了實際的類型,當被包含在多個模塊中時,會導致衝突,而這些模塊很難找到/修復。將這些包含在名稱空間或類內部是一種很好的做法。 – Indy9000 2009-04-17 08:38:24

+3

名稱衝突和匿名命名空間污染與在類內部或外部保留類型名稱無關。你可以與你的類名稱衝突,而不是你的類型定義。所以爲了避免名稱污染,請使用名稱空間。在名稱空間中聲明您的類和相關的typedef。 – 2009-04-17 08:53:14

+0

在類中放入typedef的另一個參數是使用模板化函數。例如,當一個函數收到一個包含未知字符串類型(字符串或您自己的字符串一致變體)的未知容器類型(向量或列表)時。找出容器有效載荷類型的唯一方法是使用typedef'value_type',它是容器類定義的一部分。 – Marius 2009-12-23 19:15:24

0

當typedef僅用於類本身(即聲明爲private)時,我認爲它是一個好主意。但是,正是由於你給出的原因,如果typedef需要在課堂外知道,我不會使用它。在這種情況下,我建議將它們移出課堂。

7

Typdefs絕對是很好的風格。而你所有的「我喜歡的理由」都是好的和正確的。

關於您遇到的問題。那麼,前向宣言不是一個聖盃。您可以簡單地設計代碼以避免多級別依賴性。

你可以在類之外移動typedef,但Class :: ptr比ClassPtr漂亮得多,所以我不這樣做。就像我的命名空間一樣 - 事物在範圍內保持連接。

有時候我做

Trait<Loren>::ptr 
Trait<Loren>::collection 
Trait<Loren>::map 

,它可以默認爲所有域類和一些專門爲特定的人。

3

STL始終執行此類操作 - typedef是STL中許多類的接口的一部分。

reference 
iterator 
size_type 
value_type 
etc... 

都是類型定義,它們是各種STL模板類的接口的一部分。

3

對此的另一投票是一個好主意。在編寫一個在時間和空間上都必須高效的仿真時,我開始這樣做。所有的值類型都有一個Ptr typedef,它起始於一個boost共享指針。然後,我做了一些分析,並將其中的一些更改爲boost侵入指針,而無需更改使用這些對象的任何代碼。

請注意,這僅適用於您知道將在哪些類中使用,並且所有用途具有相同要求的情況。例如,我不會在庫代碼中使用它,因爲您無法知道何時將該庫用於將要使用的上下文。

9

它作爲意圖的聲明 - 在上面的例子中,類的Lorem 旨在是參考經由升壓:: shared_ptr的計數 並存儲在 矢量。

這正是它所做的不是做的。

如果我在代碼中看到'Foo :: Ptr',我完全不知道它是shared_ptr還是Foo *(STL has :: pointer typedefs是T *,請記住)或其他。 特別如果它是一個共享指針,我根本不提供typedef,但明確地在代碼中使用shared_ptr。

其實,我很少使用Template Metaprogramming之外的typedefs。

的STL做這種類型的東西都

STL的設計,在成員函數和嵌套類型定義來定義的概念,是一個歷史的死路,現代模板庫使用免費時間函數和traits類(參考Boost.Graph),因爲它們不排除內置類型對概念建模的影響,並且因爲它使得在設計時不考慮給定模板庫的概念的類型變得更容易。

不要使用STL作爲犯同樣錯誤的理由。

1

目前我正在研究的代碼,密集使用這些類型的定義。到目前爲止,這很好。

但我注意到,經常有迭代類型定義,這些定義被分成幾個類,並且你永遠不知道你在處理什麼類型。我的任務是總結隱藏在這些typedef背後的一些複雜數據結構的大小 - 所以我不能依賴現有的接口。結合三到六層的嵌套命名空間,然後變得混亂。

所以在使用前,有幾點需要考慮

  • 沒有任何人需要這些類型定義?這個類是否被其他類使用了很多?
  • 我是否縮短使用量或隱藏課程? (在隱藏的情況下你也可以想到接口。)
  • 其他人使用的代碼?他們是如何做到的呢?他們會認爲它更容易還是會變得困惑?