2014-12-05 85 views
4

我還沒有在C++ 11標準中找到任何說無用的枚舉被廢棄的措辭,但從實用的角度來看,我想知道它們是否仍然有用。我的團隊有很多人已經得到了在轉換未範圍枚舉到作用域枚舉的習慣,但它引起了一些頭痛:非範圍枚舉仍然有用嗎?

class foo 
{ 
public: 
    enum MyEnum { One, Two, Three }; 
}; 

他們將它轉換爲:

class foo 
{ 
public: 
    enum class MyEnum { One, Two, Three }; 
}; 

這意味着這些普查員時被使用,而不是foo::One,它看起來像foo::MyEnum::One。我一直在問以下最佳實踐:

  1. 如果您轉換爲範圍的枚舉,將其移出的類和成全局範圍或命名空間範圍(以提高可用性,並避免上述後者使用示例)。
  2. 如果你保持enum unscoped,確保它在namespace/class/function/etc範圍內,這樣它就不會與其他名稱發生衝突。

兩點之間的主要區別在於#1我們不把它們放在類中,否則會增加一些冗長的間接性。

所有這些看起來都像是過於複雜化,並且似乎將枚舉已經存在於類中作爲unscoped枚舉要簡單得多。決定兩者之間的一般最佳實踐方法是什麼?

+2

切換到'enum class'的好處是您可以閱讀關於爲何添加它的所有內容;切換到'enum class'的缺點就是你上面寫的所有東西。但是,這並不能告訴我們從頭開始編寫代碼時要做什麼。 – 2014-12-05 16:40:24

+1

第二次使用有什麼問題? – Daniel 2014-12-05 16:40:48

+1

@Daniel冗長。這就像使用2個嵌套命名空間來處理對象,只有1個就足夠了。 – 2014-12-05 16:41:27

回答

5

作用域枚舉器不能隱式轉換爲其基礎類型。如果您需要將枚舉值隱式轉換爲其基礎類型,則不能使用範圍枚舉器。

時,這是非常有用的一個例子是,當你說話的API在你的控制,你的枚舉值是位標誌。 API(你不控制)期望uint32_t或其他整數類型作爲位標誌。

您可以覆蓋operator|等,以「型」,以確保一切,或讓他們產生的基本類型 - 但你enum class不能隱式轉換爲uint32_t一個元素。

另一種用於無標記的enum s我發現有用的是替換#define FOO 32樣式的宏。代替文本替換,我得到一個具有相同含義的標記,而且我不必重寫代碼庫。如果有緊緊地組合組這樣的價值觀,我可以最終達到的地步,我可以改變int論點,期待這樣的#define令牌與enum值過去了,如今的參數類型!

這使得朝着更好的代碼基地逐步遷移。

下一步可能是使用範圍的枚舉這些值,但不得不做的一切,在一次的開銷可能意味着第一步可以不考慮。完美是善的敵人。


在另一方面,如果你的枚舉其實只是一組枚舉值,以及它們在基礎類型的值是不重要的,則作用域枚舉幾乎總是比未範圍枚舉一個更好的主意。它們可以防止意外轉換爲基礎類型:如果基礎類型中的值僅僅是實現細節,則此類轉換可能導致錯誤。

這是迄今爲止我發現的最常見的用例enum s - 一個區分值的列表,其基礎類型和值僅僅是一個實現細節。