强类型枚举

文章参考

爱编程的大丙 (subingwen.cn)

1. 枚举

1.1 概述

在C/C++中的枚举来自于C,处于设计上简单的目的,枚举往往对应到整型数值。:

// 匿名枚举
enum {Male, Female};				// 0, 1
// 有名枚举
enum Color {Red, Yellow=2, Blue};	// 0, 2, 3

枚举成员默认从0开始,随后向下递增,也可以自己为某个枚举成员指定值,而下面的枚举成员依旧是递增的。

1.2 缺陷

重定义:

在C/C++中,枚举的名字以及枚举的成员名都是全局可见的,访问时也不需要::符,而是按照全局量的方式直接访问,这就很容易导致重定义的问题。

EG:

  • 代码:

    enum China {Beijing, Dongjing};
    enum Japan {Dongjing, Daban};
    
  • 分析:此时编译会报错:Redefinition of enumerator 'Dongjing'。这时由于两个Dongjing都是全局可见的,因此发生了重定义。

隐式转换:

由于C中枚举被设计为常量数值别名的版型,所有枚举的成员都可以被隐式的转换为整形,但有时我们不想这么做。

2. 强类型枚举

C++11引入枚举类,又名强类型枚举(strong-typed enum)

定义:

// 默认底层类型为int
enum class Color {Red, Green, Blue};
// 指定类型:
enum class Color: char {Red, Green, Blue};

其中:

  • 指定的底层类型可以是除了wchar_t以外的任何整形。
    • wchar_t:双字节类型或宽字符类型,是C/C++的一种扩展的存储方式,一般为16位或32位。主要用在国际程序的实现中。

优点:

  • 强作用域:强类型枚举成员的名称不会被输出到其父级作用域空间,且必须使用有名枚举,例如:Color::Red
  • 转换类型限制:强枚举类型的值不能和整形进行隐式的转换

注意:

  • 在声明强类型枚举的时候,除了使用enum class,也可以使用enum struct,二者没有区别。
  • enum class没有共有、私有之分,也不会使用模板来支持泛化的声明。

EG:

  • 代码:

    enum class China { Shanghai, Dongjing, Beijing, Nanjing, };
    enum class Japan:char { Dongjing, Daban, Hengbin, Fudao };
    int main()
    {
        int m = Shanghai;           // error
        int n = China::Shanghai;    // error
        if ((int)China::Beijing >= 2)
        {
        	cout << "ok!" << endl;
        }
        cout << "size1: " << sizeof(China::Dongjing) << endl;
        cout << "size2: " << sizeof(Japan::Dongjing) << endl;
        return 0;
    }
    
  • 分析:

    • 第5行:错误。强类型枚举具有强作用域,必须通过枚举名::才能访问到枚举成员。
    • 第6行:错误。强类型枚举禁止枚举成员和整形进行隐式转换。
    • 第7行:正确。在将强类型枚举的枚举成员和整形进行比较之前做了强制类型转换。
    • 第11行:输出4,因为强类型枚举的地城类型值默认为int
    • 第12行:输出1,因为显式制定了该强类型枚举的类型为char

3. 对原有枚举进行扩展

强类型枚举虽然好用,但它带有浓厚的C++风格,和原有的属于C的枚举不相容。为了配合强类型枚举,C++11对原有的枚举类型进行了扩展:

  • 底层类型:可以显式指定枚举的底层类型,方式和强类型枚举一致,在枚举名称后加上:type,且type可以是除了wchar_t之外的任何整形。如果不指定,默认依旧是int类型。

    enum Colors: char{ Red, Yellow, Blue };
    

    注意:不像强类型枚举,扩展后枚举依旧支持隐式类型的转换。

    enum Colors: char{ Red, Yellow, Blue };
    int n = Colors::Red;
    
  • 作用域:C++11规定枚举成员的名字除了输出到父级作用域,还在枚举类型定义的作用域中有效:

    enum Colors: char{ Red, Yellow, Blue };
    int main(void){
        // C++11之前
        Colors c1 = Red;
        // C++11的扩展语法
        Colors c2 = Colors::Red;
        return 0;
    }
    
posted @ 2023-12-11 14:45  BinaryPrinter  阅读(70)  评论(0编辑  收藏  举报