zoukankan      html  css  js  c++  java
  • 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.

             这个方法稍微繁琐一点,但是满足了我们的要求:使用枚举类型(带来枚举类型固有的优点);使得枚举类型具有命名空间的特点(虽然起这个作用的并不是枚举类型本身).

  • 相关阅读:
    896. Monotonic Array单调数组
    865. Smallest Subtree with all the Deepest Nodes 有最深节点的最小子树
    489. Robot Room Cleaner扫地机器人
    JavaFX
    《Python CookBook2》 第一章 文本
    《Python CookBook2》 第一章 文本
    《Python CookBook2》 第一章 文本
    《Python CookBook2》 第一章 文本
    《Python CookBook2》 第一章 文本
    《Python CookBook2》 第一章 文本
  • 原文地址:https://www.cnblogs.com/rollenholt/p/2405454.html
Copyright © 2011-2022 走看看