1. 程式人生 > >【C++】列舉(enum)

【C++】列舉(enum)

目錄

宣告和定義

常規使用方法

自定義列舉量的值

列舉的取值範圍(一般不用考慮)

列舉應用

改進後的列舉

原有列舉的問題

改進--強型別列舉

專案中的強型別列舉程式碼片段

參考


宣告和定義

enum enumType {Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday};

這句話有兩個作用:

第一:宣告enumType為新的資料型別,稱為列舉(enumeration);

第二:宣告Monday、Tuesday等為符號常量,通常稱之為列舉量,其值預設分別為0-6。(後面會介紹怎樣顯式的初始化列舉量

的值)這些符號常量只能與整形進行型別轉換。

常規使用方法

enum enumType {Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday};
enumType Weekday;
//或者在初始化的時候進行申明
//enum enumType {Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday}Weekday;

在不進行強制轉換的前提下

只能將定義的列舉量賦值給該種列舉的變數,如:Weekday = Monday;或者Weekday = Sunday;

不能將其他值賦給列舉變數,如:Weekday = 10;這是不允許的,因為10不是列舉量

在允許使用強制轉換的前提下,

Weekday = enumType(2);等同於:Weekday = Wednesday;但有一點需要注意,如果你使用Weekday = enumType(20);結果將是不確定的,這麼做不會出錯,但得不到想要的結果。

問題

(1)那列舉變數能不能進行算術運算呢?

如:int a=Monday;這是允許的,因為列舉量是符號常量,這裡的賦值編譯器會自動把列舉量轉換為int型別。

(2)那列舉變數能不能進行算術運算呢?

Weekday++;

Weekday = Monday + Tuesday;這是非法的,因為這些操作可能導致違反型別限制。反正就是C++沒有定義這種算術運算子的操作。

(3)那麼列舉量能不能參與其他型別變數的運算呢?

int a;a = 1 + Monday;這是允許的,因為編譯器會自動把列舉量轉換為int型別。

總結:對於列舉,只定義了賦值運算子,沒有為列舉定義算術運算。

自定義列舉量的值

(1)前面講通過定義enum enumType {Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday};

列舉量Monday、Tuesday等的值預設分別為0-6,我們可以顯式的設定列舉量的值

enum enumType {Monday=1, Tuesday=2, Wednesday=3, Thursday=4, Friday=5, Saturday=6, Sunday=7};

指定的值必須是整數

(2)也可以只顯式的定義一部分列舉量的值:

enum enumType {Monday=1, Tuesday, Wednesday=1, Thursday, Friday, Saturday, Sunday};這樣Monday、Wednesday均被定義為1,則Tuesday=2,Thursday、Friday、Saturday、Sunday的值預設分別為2、3、4、5。

總結:未被初始化的列舉值的值預設將比其前面的列舉值大1,列舉量的值可以相同。

列舉的取值範圍(一般不用考慮)

前面講到可以通過強制轉換將其他型別值賦給列舉變數:Weekday = enumType(2);這是合法的;但是Weekday = enumType(20);是非法的。這裡涉及列舉取值範圍的概念:列舉的上限是 大於最大列舉量的 最小的2的冪,減去1;

列舉的下限有兩種情況:一、列舉量的最小值不小於0,則列舉下限取0;二、列舉量的最小值小於0,則列舉下限是 小於最小列舉量的 最大的2的冪,加上1。

舉例來講:

假如定義 enum enumType1 { First=-5,Second=14,Third=10 };則列舉的上限是16-1=15(16大於最大列舉量14,且為2的冪);  列舉的下限是-8+1=-7(-8小於最小列舉量-5,且為2的冪);

列舉應用

個人覺得列舉switch是最好的搭檔:
 

enum enumType{Step0, Step1, Step2}Step=Step0;//注意這裡在宣告列舉的時候直接定義了列舉變數Step,並初始化為Step0

switch (Step)
{
  case Step0:{...;break;}
  case Step1:{...;break;}
  case Step2:{...;break;}
  default:break;
}

另外列舉還有一種少見的用法是 enum { one ,two ,three};  就是不指定一個名字,這樣我們自然也沒法去定義一些列舉型別了。此時就相當於static const int one = 0;這樣定義三個常量一樣。然後用的話就是int no = one。

改進後的列舉

原有列舉的問題

強型別列舉(Strongly-typed enums),號稱列舉型別,是C++11中的新語法,用以解決傳統C++列舉型別存在的缺陷:

(1)傳統C++中列舉常量被暴漏在外層作用域中,這樣若是同一作用域下有兩個不同的列舉型別,但含有相同的列舉常量也是不可的,比如:

enum Side{Right,Left};
enum Thing{Wrong,Right};

這是不能一起用的。 
(2)另外一個缺陷是傳統列舉值總是被隱式轉換為整形,使用者無法自定義型別。C++11中的強型別列舉解決了這些問題。

改進--強型別列舉

強型別列舉使用enum class語法來宣告,如下:

enum class Enumeration{
 VAL1,
 VAL2,
 VAL3=100,
 VAL4
};

這樣,列舉型別時安全的,列舉值也不會被隱式轉換為整數,無法和整數數值比較,比如(Enumeration::VAL4==10會觸發編譯錯誤),就算Enumeration::VAL3==100也是編譯不通過,畢竟型別不一樣,你怎麼比較。

 另外列舉型別所使用的型別預設為int型別,也可指定其他型別,比如:

enum class Enum:unsigned int{VAL1,VAL2};

正如前面所說,強型別列舉能解決傳統列舉不同列舉類下同列舉值名的問題,使用列舉型別的列舉名時,必須指明所屬範圍,比如:Enum::VAL1,而單獨的VAL1則不再具有意義。

還有一點值得說明的是C++11中列舉型別的前置宣告也是可行的,比如:

enum class Enum;
enum class Enum1:unsigned int;

我能想到的小例子:

例一

enum class Mytest { Step0, Step1, Step2 }Step;


int main()
{
    Step = Mytest::Step0;

    switch (Step)
    {
    case Mytest::Step0: {printf("Step0\n"); break; }
    case Mytest::Step1: {printf("Step1\n"); break; }
    case Mytest::Step2: {printf("Step2\n"); break; }
    default:break;
    }

    return 0;

}

結果為:

Step0

例二

enum class Enum:unsigned int { VAL1, VAL2 };

int main()
{
   
    Enumeration x = Enumeration::VAL3;
    Enum p = Enum::VAL1;
    int q = (int)p;
    cout << q << endl;
    return 0;

}

 結果為:

0

專案中的強型別列舉程式碼片段

1、影象處理

enum class Color{RED,BLUE,YELLOR,BLACK,WHITE};

2.交通燈

enum class TrafficLight{RED,YELLOR,GREEN};

強型別列舉值具有傳統列舉的功能——命名列舉值,同時又具有類的特點——具有類域的成員和無法進行預設的型別轉換。所以也稱之為列舉類——enmu class

列舉類的底層資料必須是有符號或無符號整型,比如char unsigned int unsigned long,預設為int。

3.前置宣告應用

enmu class Color:char;  //前置宣告列舉類
void Foo(Color*p);        //前置宣告的使用
//....................
enum class Color:char{RED,GREEN,BLACK,WHITE};                       //前置宣告的定義

 

參考

https://blog.csdn.net/bruce_0712/article/details/54984371

https://www.cnblogs.com/byteHuang/p/7092010.html(原有enum列舉的例子)