天天看點

enum枚舉類型用法

文章目錄

      • 1. 枚舉類型和枚舉變量
        • 1.1 枚舉類型的定義和聲明
        • 1.2 枚舉變量的定義和聲明
      • 2. 枚舉變量和枚舉常量的關聯對應
      • 3. 枚舉類型和變量的應用
        • 3.1 作為判斷語句中的邏輯
        • 3.2 一次定義多個常量
        • 3.3 限定變量的範圍
        • 3.4 enum hack:用于初始化類内數組
      • 4. 總結
      • 5. 參考資料

在實際的程式設計應用中,有的變量隻有幾種可能的取值,譬如說一個家族的幾個成員,性别的兩種可能等等。C++為這種類型的變量的定義提供了 enum關鍵字。

要使用枚舉類型的變量,首先需要先定義一個枚舉類型名,再聲明變量是該枚舉類型的。

1. 枚舉類型和枚舉變量

1.1 枚舉類型的定義和聲明

之是以被稱為枚舉類型,就是因為命名常量是作為資料類型定義的一部分而枚舉或列出的,以下是枚舉類型聲明的示例:

enum Roster { 	//該語句定義了Roster這一枚舉類型 
	Tom,
	Sharon, 
	Bill, 
	Teresa, 
	John
}; 

// 定義匿名的枚舉變量,隻能使用a這一個枚舉類型的變量,不能再定義其他該類型的枚舉變量
enum  {Jan=1,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,dec} a;

// typedef  enum則是用來定義一個資料類型,那麼該類型的變量值隻能在enum定義的範圍内取
typedef enum  {Jan=1,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,dec} Day;

// 定義enum/枚舉類型的同時,聲明變量
enum Month {Jan=1,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,dec} a,b;
           

上述例子中的Tom、Sharon等稱為 枚舉元素 或 枚舉常量(本人更傾向于稱其為枚舉常量,因為這樣可以反映其性質),它們是使用者自定義的辨別符而已。

預設/不顯示說明情況下,編譯器設定第一個枚舉量為 0,下一個為 1,以此類推(沒有顯示說明下步長為1)。在上述示例中,Tom 的值将是 0,Sharon 的值為 1,等等。最後一個枚舉量 John 的值為 4。

1.2 枚舉變量的定義和聲明

enum 語句實際上并沒有建立任何變量,隻是定義了一個枚舉類型。當以後建立這個資料類型的變量時,它們看起來就是整數,并且這些整數的值被限制在與枚舉集合中的符号名稱相關聯的整數上。以下語句定義了兩個 Roster 資料類型的變量:

enum Roster grandfather; //該語句聲明了一個枚舉類型的變量
enum Roster student;
           

此語句的形式與其他任何變量定義一樣,首先是資料類型名稱,然後是變量名稱。資料類型名稱是 Roster,而不是 enum Roster。

注意:

  • 不同枚舉類型中的枚舉常量的名字必須互不相同;
  • 同一枚舉類型中的不同的枚舉常量可以具有相同的值。

前述語句已經建立 student 這一枚舉變量,也可直接定義并指派,操作如下:

student = Sharon;
enum Roster stu1 = John;
           

2. 枚舉變量和枚舉常量的關聯對應

如前所述,預設情況/不顯示說明的情況下,枚舉清單中的符号将被賦給整數值 0、1、2 等等。

枚舉清單中的符号如果不合适,則可以指定要賦給的值,如以下示例所示:

如果為枚舉符号指派,則它們必須是整數。以下指派語句将産生錯誤:

雖然沒有要求按升序排列賦給的整數值,但一般預設是這樣。

如果在指派時省略了一個或多個符号,則它們将被賦給一個預設值,以下兩個示例:

//示例1
enum Colors { red, orange, yellow = 9, green, blue };
           

在該示例中,命名常量 red 将被指派為 0,orange 将為 1,yellow 将為 9,green 将為 10,blue 将為 11。

//示例2
enum Rooms { livingroom = 1, den, bedroom, kitchen };
           

在該示例中,livingroom 被指派為 1,den 将為 2,bedroom 将為 3,kitchen 将為 4。

3. 枚舉類型和變量的應用

3.1 作為判斷語句中的邏輯

  • 枚舉常量和枚舉變量可以用于判斷語句,實際用于判斷的是其中實際包含的值

    以上 if 條件語句中Sharon沒有引号包圍。因為它是一個枚舉/命名常量,而不是字元串常量。也即是枚舉資料類型的目的之一是符号名稱有助于使程式自我解釋。但是,由于這些名稱不是字元串,它們僅在程式中使用。在使用 Roster 資料類型的示例中,以下兩個語句将輸出一個2,而不是名稱 Sharon:

//使用正常的手段輸出無法輸出枚舉常量所對應的字元串,因為枚舉常量為整型值
Roster student1 = Sharon;
cout << student1;
//語句輸出:
//>2
           
  • 即使枚舉資料類型中的值實際存儲為整數,也不能總是将整數值替換為符号名稱。例如,不能使用下面語句将 Sharon 指派給 student:
  • 但是,可使用整數值或枚舉常量名稱來測試枚舉變量。例如,以下兩個 if 語句是等效的:
if (student == Bill) 
if (student == 2)
           
  • 還可以使用關系運算符來比較兩個枚舉變量,實際比較的是枚舉變量實際包含的值的大小。例如,以下 if 語句确定存儲在 student1 中的值是否小于存儲在 student2 中的值。如果 student1 等于 Bill,student2 等于 John,則該語句為 true。但是,如果 student1 等于 Bill,而 student2 等于 Sharon,則該語句将為 false。
  • 因為枚舉資料類型的符号名稱與整數值相關聯,是以它們可以在 switch 語句中使用,如下面的程式所示,該程式還示範了可以隻使用枚舉類型,而不實際建立該枚舉類型的任何枚舉變量。
#include <iostream>
using namespace std;
	
// Declare the enumerated type
enum Roster { Tom = 1, Sharon, Bill, Teresa, John };
// Sharon - John will be assigned default values 2-5.
int main() {
	int who;
	cin >> who;
	switch (who) {
		case Tom :
	    	cout << "Tom's birthday is January 3.\n";
	        break;
	    case Sharon :
	        cout << "Sharon's birthday is April 22.\n";
	        break;
	    case Bill :
	        cout << "Bill's birthday is December 19.\n";
	        break;
	    case Teresa :
	        cout << "Teresa's birthday is February 2.\n";
	        break;
	    case John :
	        cout << "John's birthday is June 17.\n";
	        break;
	    default :
	        cout << "Invalid selection\n";
	}
	return 0;
}
	
//程式運作結果:
//>2
//Sharon's birthday is April 22.
           

3.2 一次定義多個常量

比如程式中處理的問題與星期幾有關,可能要将星期一轉換為數字1,星期二轉換為數字2,一直到數字7,在不用

enum

關鍵字的情況下,可以使用

define

來定義,但是會覺得很麻煩,因為因為要一個個的定義,星期的就隻有7天,如果是月份,一年有12個月份,那就要寫12個define,非常不友善,相反,如果使用enum的話就會非常的友善。

#include<stdio.h>
 
enum week {Mon=1,Tue,Wed,Thu,Fri,Sat,Sun};
 
int main()
{
    printf("%d",Tue);
    return 0;
}
           

這樣定義後,Mon的值為1,Tue的值為2,Wed的值為3,依次類推。 然後就可以像使用define之後的常量一樣的使用定義的7個值了。

當然也可以為每個枚舉的變量都指派,這樣就和全都用define定義是一樣的了。

3.3 限定變量的範圍

比如我們的應用程式中要處理有關月份的東西,顯然月份隻能取1-12中的某個數字,為了保證程式的正确性和健壯性,我們應該使用enum。

#include<stdio.h>
 
enum Month {Jan=1,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,dec};
 
int main()
{
    enum Month a =  Feb;
    printf("%d",a);
    return 0;
}
           

比如像這樣,定義的枚舉類型 a 的取值隻能是那12個變量中的一個,如果賦予了其他的變量,編譯器就會報錯。

3.4 enum hack:用于初始化類内數組

摘自《Effective C++》條款02

有時候編譯器(錯誤地)不允許“static 整數型 class常量”完成“in class初值設定”,這時可改用所謂的“the enum hack"補償做法。

其理論基礎為:一個屬于枚舉類型(enumerated type的數值可充當ints來使用。示例如下:

class GamePlayer {
private:
	enum { NumTurns = 5 }; //"the enum hack"——令NumTurns
						   //成為5的一個記号名稱
	int scores[NumTurns];  //這就沒問題了
	...
};

int main() {
	//非類内的靜态整形常量是可以對數組進行初始化的,以下代碼不會報錯
	const static int arraySize = 5;
	int array[arraySize];
}
           
  • enum hack行為某方面來說比較像#define而不像const,例如取const常量是合法的,但是#define和enum取位址就是不合法的;
  • 如果不想讓使用者獲得一個pointer或reference來指向你定義的某整數常量,則以enum可代替const int實作該限制;
  • 有些編譯器會為const int類型常量另開空間存儲,而enum變量卻不會,有時會更省空間。

4. 總結

  • 枚舉常量

    之間用逗号隔開,最後一個枚舉常量之後不需要逗号;
  • 整個枚舉類型定義語句的最後需要一個分号;
  • Roster是該枚舉類型的名字,這是一個可選項;
  • 不能對枚舉常量進行指派操作(定義枚舉類型時除外);

  • 枚舉常量和枚舉變量可以用于判斷語句,實際用于判斷的是其中實際包含的值;

  • 一個整數不能直接指派給一個枚舉變量,必須用該枚舉變量所屬的枚舉類型進行類型強制轉換才行;

  • 使用正常的手段輸出無法輸出枚舉常量所對應的字元串,因為枚舉常量為整型值;
  • 在使用枚舉變量的時候,我們不關心其值的大小,而是其表示的狀态;
  • enum用來定義一系列宏定義常量,相當于一系列的

    #define xx xx

    ,當然它後面的辨別符也可當作一個類型辨別符;
  • typedef enum

    則是用來定義一個資料類型,那麼該類型的變量值隻能在enum定義的範圍内取。兩者在這點上是沒有差别的。
  • 對enum變量取位址是不合法的,類似于#define的行為,對#define取位址也不合法(見Effective C++條款02)

5. 參考資料

  1. C語言——enum枚舉類型用法解析
  2. C++ enum枚舉用法攻略(超詳細)
  3. C++ Primer(第5版)
  4. C語言之enum的用法和注意事項(枚舉類型)

繼續閱讀