强枚举类型 1年前

编程语言
589
强枚举类型

12. 强枚举类型

1. 枚举

1.1 枚举的使用

枚举类型是C及C++中一个基本的内置类型,不过也是一个有点”奇怪”的类型。从枚举的本意上来讲,就是要定义一个类别,并穷举同一类别下的个体以供代码中使用。 由于枚举来源于C,所以出于设计上的简单的目的,枚举值常常是对应到整型数值的一些名字

比如:

// 匿名枚举
enum {Red, Green, Blue};
// 有名枚举
enum Colors{Red, Green, Blue};

在枚举类型中的枚举值编译器会默认从0开始赋值,而后依次向下递增,也就是说 Red=0,Green=1,Blue=2。


1.2 枚举的缺陷

C/C++的enum有个很”奇怪” 的设定,就是具名(有名字)的enum类型的名字,以及 enum 的成员的名字都是全局可见的 这与 C++中具名的 namespace、class/struct 及 union 必须通过名字::成员名的方式访问相比是格格不入的,编码过程中一不小心程序员就容易遇到问题。

比如∶

enum China {Shanghai, Dongjing, Beijing, Nanjing};
enum Japan {Dongjing, Daban, Hengbin, Fudao};

上面定义的两个枚举在编译的时候,编译器会报错,具体信息如下:

error C2365: “Dongjing”: 重定义;以前的定义是“枚举数”

错误的原因上面也提到了,在这两个具名的枚举中Dongjing是全局可见的,所有编译器就会提示其重定义了。

另外,由于C中枚举被设计为常量数值的”别名”的本性,所以枚举的成员总是可以被隐式地转换为整型,但是很多时候我们并不想这样。


2. 强类型枚举

2.1 优势

针对枚举的缺陷,C++11标准引入了一种新的枚举类型,即枚举类,又称强类型枚举(strong-typed enum)

声明强类型枚举非常简单,只需要在 enum 后加上关键字 class。

// 定义强类型枚举
enum class Colors{Red, Green, Blue};

强类型枚举具有以下几点优势∶


  • 强作用域,强类型枚举成员的名称不会被输出到其父作用域空间。

    • 强类型枚举只能是有名枚举,如果是匿名枚举会导致枚举值无法使用(因为没有作用域名称)。
  • 转换限制,强类型枚举成员的值不可以与整型隐式地相互转换。


  • 可以指定底层类型。强类型枚举默认的底层类型为 int,但也可以显式地指定底层类型,
具体方法为在枚举名称后面加上∶type,其中 type 可以是除 wchar_t 以外的任何整型。比如:

enum class Colors :char { Red, Green, Blue };

wchar_t 是什么?

双字节类型,或宽字符类型,是C/C++的一种扩展的存储方式,一般为16位或32位,所能表示的字符数远超char型。 主要用在国际化程序的实现中,但它不等同于 unicode 编码。unicode 编码的字符一般以wchar_t类型存储。

了解了强类型枚举的优势之后,看一段程序:

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行:该行的代码有两处错误
    1. 强类型枚举属于强作用于类型,不能直接使用,枚举值前必须加枚举类型
    2. 强类型枚举不会进行隐式类型转换,因此枚举值不能直接给int行变量赋值(虽然强类型枚举的枚举值默认就是整形,但其不能作为整形使用)。
  • 第6行:语法错误,将强类型枚举值作为整形使用,此处不会进行隐式类型转换
  • 第7行:语法正确,强类型枚举值在和整数比较之前做了强制类型转换。
  • 第11行:打印的结果为4,强类型枚举底层类型值默认为int,因此占用的内存是4个字节
  • 第12行:打印的结果为1,显示指定了强类型枚举值的类型为char,因此占用的内存大小为1个字节,这样我们就可以节省更多的内存空间了。

2.2 对原有枚举的扩展

相比于原来的枚举,强类型枚举更像是一个属于C++的枚举。 但为了配合新的枚举类型,C++11还对原有枚举类型进行了扩展:

原有枚举类型的底层类型在默认情况下,仍然由编译器来具体指定实现。 但也可以跟强类型枚举类一样,显式地由我们来指定。 其指定的方式跟强类型枚举一样,都是枚举名称后面加上∶type

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

关于作用域,在C++11中,枚举成员的名字除了会自动输出到父作用域,也可以在枚举类型定义的作用域内有效。比如:

enum Colors : char { Red, Green, Blue };
int main()
{
    Colors c1 = Green;          // C++11以前的用法
    Colors c2 = Colors::Green;  // C++11的扩展语法
    return 0;
}

上面程序中第4、5行的写法都是合法的。

我们在声明强类型枚举的时候,也可以使用关键字enum structenum structenum class 在语法上没有任何区别(enum class 的成员没有公有私有之分,也不会使用模板来支持泛化的声明 )。

image
EchoEcho官方
无论前方如何,请不要后悔与我相遇。
1377
发布数
439
关注者
2378294
累计阅读

热门教程文档

Vue
25小节
Javascript
24小节
Spring Cloud
8小节
React Native
40小节
Dart
35小节
广告