天天看點

C++11新特性之九:strongly-typed enums

一.傳統枚舉類型的缺點

1.作用域沖突

傳統C++中枚舉元素被暴漏在外層作用域中,這樣若是同一作用域下有兩個不同的枚舉類型,但含有相同的枚舉元素,就會産生沖突。

enum EnumOne
{
    A = 1,
    B = 2
};

enum EnumTwo
{
    A = 1,
    C = 2
};
           

error C2365: “A”: 重定義;以前的定義是“枚舉數”

2.無關的枚舉元素可以比較

另外一個缺陷是傳統枚舉類型的枚舉元素總是被隐式轉換為整形,這就使得毫無關系的兩個枚舉類型的枚舉元素可以進行比較。

enum EnumOne
{
    A = 1,
    B = 2
};

enum EnumTwo
{
    C = 1,
    D = 2
};

int main()
{
    if (EnumOne::A == EnumTwo::C)// 直接寫A==C也行
    {
          cout << "equals" << endl;// 輸出equals
    }

    if (EnumOne::A == 1)
    {
          cout << "equals too" << endl;// 輸出equals too
    }

    system("pause");
    return 0;
}
           

二.強類型枚舉

強類型枚舉(Strongly-typed enums),号稱枚舉類型,是C++11中的新文法,用以解決傳統枚舉類型存在的缺點。

它不會将枚舉元素暴露到外層作用域中,也不會隐式轉換為整形,并且可以擁有使用者指定的元素類型(傳統枚舉也增加了這個性質)

強類型枚舉使用enum class文法來聲明,如下:

enum class EnumOne
{
    A = 1,
    B = 2
};

enum class EnumTwo
{
    A = 1,
    C = 2
};
           

此時這兩個枚舉即使有同名元素A,編譯器不會報錯了。

但是這兩個枚舉中枚舉元素的比較,或者枚舉元素與整數的比較都會報錯。例如:

enum class EnumOne
{
    A = 1,
    B = 2
};

enum class EnumTwo
{
    A = 1,
    D = 2
};

int main()
{
    if (EnumOne::B == EnumTwo::D)// A和B必須帶上作用域,不能直接寫成A==B,此時單獨的A或B不再有意義
    {
          cout << "equals" << endl;// 輸出equals
    }


    if (EnumOne::B == 2)
   {
          cout << "equals too" << endl;// 輸出equals too
   }
    system("pause");
    return 0;
}
           

兩處相等判斷都在編譯時報錯:error C2678: 二進制“==”: 沒有找到接受“EnumOne”類型的左操作數的運算符(或沒有可接受的轉換)

三.比較

傳統枚舉類型和強枚舉類型都支援使用者指定元素類型(預設為int類型)

enum EnumA : int { A,B};
enum class EnumB : long {C,D};
           

還有一點值得說明的是C++11中枚舉類型的前置聲明也是可行的,比如:

enum Enum1;                     // 不合法
enum Enum2 : unsigned int;      // 合法的 C++11
enum class Enum3;               // 合法的 C++11,預設為int 
enum class Enum4 : unsigned int;// 合法的 C++11
enum Enum2 : unsigned short;    // 不合法的 C++11,Enum2已被聲明為unsigned int
           
enmu class Clolor:char;   //前置聲明枚舉  
void Foo(Color*p);        //前置聲明的使用  
//....................  
enum class Color:char{RED,GREEN,BLACK,WHITE}; //前置聲明的定義 
           

四.一個例子

#include <iostream>
using namespace std;
int main()
{
    enum class Status {Ok, Error};
    enum struct Status2{Ok, Error};
    Status flag = Status::Ok;
    if(flag == Status::Ok)
    {
         cout << "equals" <<endl;//equals
    }

    //int n=flag;                   // 錯誤,不會隐式轉換為int
    int n = static_cast<int>(flag); // 正确, n = 0,枚舉元素預設從0開始
    enum class EnumOne : char { A = 1, B = 2};   //指定枚舉的底層資料類型
    enum class EnumTwo : unsigned int { C = 1, D = 2, Dbig = 0xFFFFFFF0U };

    cout << sizeof(EnumOne::A) << endl;          // 1
    cout << (unsigned int)EnumTwo::Dbig << endl; // 編譯器輸出一緻,4294967280
    cout << sizeof(EnumTwo::D) << endl;          // 4
    cout << sizeof(EnumTwo::Dbig) << endl;       // 4

    system("pause");
    return 0;
}
           
上一篇: 安裝fis3失敗
下一篇: RFC1340RFC1340