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


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

<!--[if !supportLists]-->1           <!--[endif]-->不支持組合特性,也即FlagsAttribute屬性;

<!--[if !supportLists]-->2           <!--[endif]-->不支持toString方法,轉換為字符串需要特別的函數實現;

<!--[if !supportLists]-->3           <!--[endif]-->不支持命名空間的特性.

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

首先給出一段摘自MSDN的C#代碼:

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#的兩個區別:

<!--[if !supportLists]-->1           <!--[endif]-->在C++中,enum向int的轉化是隱式進行的,不需要強制的類型轉換;

<!--[if !supportLists]-->2           <!--[endif]-->在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.

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

<!--[if !supportLists]-->1           <!--[endif]-->仍然使用枚舉聲明,但是增加前綴,例如 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 };

<!--[if !supportLists]-->2           <!--[endif]-->不再使用枚舉聲明,使用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的用法

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

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

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM