C++ enum類型的一個更好的用法

C++ enum類型的一個更好的用法

 

enum 類型是c++的一個基本的類型,用於聲明可以枚舉的常量.相對於C#enum, c++enum有幾個缺陷:

1           不支持組合特性,也即FlagsAttribute屬性;

2           不支持toString方法,轉換爲字符串需要特別的函數實現;

3           不支持命名空間的特性.

前面的兩個比較明顯,我們只是討論第3個缺陷及其的一個彌補方法.

首先給出一段摘自MSDNC#代碼:

public class EnumTest

{

    enum Days {Sat=1, Sun, Mon, Tue, Wed, Thu, Fri};

    static void Main()

    {

                  int x = (int)Days.Sun;

int y = (int)Days.Fri;

        Console.WriteLine("Sun = {0}", x);

        Console.WriteLine("Fri = {0}", y);

    }

}

代碼 1 C#使用枚舉

在上面的代碼中,枚舉類型Days不僅是一個類型,而且在使用當中還起到了命名空間的作用.

如果使用C++的代碼,應該是:

enum Days {Sat=1, Sun, Mon, Tue, Wed, Thu, Fri};

    int main()

    {

                  int x = Sun;        //注意這裏!!

int y = Fri;        //注意這裏!!

        printf("Sun = {%d}", x);

        printf ("Fri = {%d}", y);

                   return 0;

    }

代碼 2 C++使用枚舉

在這裏,enum類型,我們注意到C++C#的兩個區別:

1           C++,enumint的轉化是隱式進行的,不需要強制的類型轉換;

2           C++,使用枚舉類型不必帶有類型限定名,直接使用,類似於使用宏.

對於第一個區別,未必是一件壞事;但是對於第二個,則有明顯的問題.

我們列舉一個在c++中由於區別2而帶來問題的一個例子.假如我們聲明瞭另外的一個枚舉類型Planets:  enum Planets {Moon, Earth, Sun }; 顯然,包含這個類型聲明的頭文件和代碼 2是不能在一個編譯單元中使用的,因爲Sun意義有分歧.這顯然是C++枚舉類型缺乏命名空間所帶來的後果;C#則沒有這樣的問題.

         當然,c++這樣設計也有一些好處,我們也使用一個例子說明:

         class File

{

public:

         enum OpenMode{ READ, WRITE};

         void open( OpenMode , const char* filename );

};

int main()

{

         File file;

         file.open(OpenMode::READ,"c://1.txt");

         return 0;

}

代碼 3 C++枚舉不使用限定名適合的例子

我們注意到,這裏的代碼可讀性非常好.但是這段代碼的特點是:枚舉類型嵌套的定義在父類型裏面.但是在很多的情況下,枚舉類型具有獨立的意義,不必嵌套在任何的類型裏面,例如上面的代碼 1.

要解決這個問題,傳統的做法有兩種:

1           仍然使用枚舉聲明,但是增加前綴,例如 enum Days{Day_Sat=1, Day_Sun, Day_Mon, Day_Tue, Day_Wed, Day_Thu, Day_Fri}; enum Planets{ Planet_Moon, Planet_Earth, Planet_Sun };

2           不再使用枚舉聲明,使用int替代,並且嵌套在類型之中,例如

struct Days

{

         const static int Sat = 1;

         const static int Sun = 2;

         const static int Mon = 3;

         const static int Tue = 4;

         const static int Wed = 5;

         const static int Thu = 6;

         const static int Fri = 7;

};      

struct Planets

{

         const static int Moon = 0;

         const static int Earth = 1;

         const static int Sun = 1;

};

         第一個方法顯得累贅,第二個方法則失去了枚舉類型的固有優點;我們希望提供一種把兩者結合起來的方法.

         好了,囉嗦了這麼多,該拿出我們的乾貨了.下面是我們的方法:

         namespace Days

{

         enum Days_ {Sat=1, Sun, Mon, Tue, Wed, Thu, Fri};

};

typedef Days::Days_ Days;

 

int main()

{

         Days d = Days::Sun;//1

         int x = d;  

         printf("Sun = {%d}", x);

         return 0;

 

}

代碼 4 C++ enum的用法

         代碼 41,Days出現在兩次,第一次是用作類型,實際上指向Days::Days_,第二次是用作命名空間,指向命名空間Days.那麼這個魔法是怎麼實現的呢?顯然,編譯器提供了智能化,爲我們完成了這個工作.

         枚舉類型Days_爲什麼要有一個下劃線? 我們的目的是提醒用戶不要使用Days::Days_,而是使用我們定義的類型別名Days.

         這個方法稍微繁瑣一點,但是滿足了我們的要求:使用枚舉類型(帶來枚舉類型固有的優點);使得枚舉類型具有命名空間的特點(雖然起這個作用的並不是枚舉類型本身).

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章