c++ strongly typed enum

Author: Su Bingwen
Link: https://subingwen.cn/cpp/enum/

1. Enumeration

1.1 Use of enumeration

The enumeration type is a basic built-in type in C and C++, but it is also a somewhat "weird" type. From the original intention of enumeration, it is to define a category and exhaustively enumerate the individuals under the same category for use in code. Since enumeration comes from C, for the purpose of simplicity in design, enumeration values ​​are often some names corresponding to integer values, such as:

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

The enumeration value compiler in the enumeration type will assign values ​​from 0 by default, and then increase downwards, that is to say, Red=0, Green=1, Blue=2.

1.2 Defects of enumeration

C/C++'s enum has a very "strange" setting, that is, the name of the enum type with a name (with a name), and the names of the members of the enum 全局可见的. This is incompatible with the named namespace, class/struct, and union in C++ that must be accessed through the name::member name method, and the 编码programmer will be caught if he is not careful during the process 容易遇到问题. For example:

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

When compiling the two enumerations defined above, the compiler will report an error. The specific information is as follows:

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

The reason for the error is also mentioned above. In these two named enumerations Dongjing 是全局可见的, all compilers will prompt for their redefinition.

In addition, due to the nature of enumerations in C being designed as "aliases" for constant values, members of enumerations can always be implicitly converted to integers, but many times we don't want this.

2. Strongly typed enum

2.1 Advantages

In response to the defects of enumeration, the C++11 standard introduces a new enumeration type, that is, enumeration class, also known as strong-typed enumeration (strong-typed enum). Declaring a strongly typed enumeration is as simple as adding the keyword class after the enum. For example:

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

Strongly typed enumerations have the following advantages:

  • 强作用域, the names of strongly typed enumeration members are not exported to their parent scope space.

  • 强类型枚举只能是有名枚举, if it is an anonymous enumeration, the enumeration value cannot be used (because there is no scope name).

  • 转换限制, the value of a strongly typed enumeration member 不可以与整型隐式地相互转换.

  • 可以指定底层类型. The default underlying type of a strongly typed enumeration is int, but the underlying type can also be specified explicitly by adding: type after the enumeration name, where type can be any integer type except wchar_t. for example:

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

What is wchar_t?
Double-byte type, or wide character type, is an extended storage method of C/C++, generally 16-bit or 32-bit, and the number of characters that can be represented far exceeds that of char type.
Mainly used in the implementation of internationalized programs, but it is not equivalent to unicode encoding. Unicode-encoded characters are generally stored in wchar_t type.

After understanding the advantages of strongly typed enumeration, let's look at another program:


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;
}
  • Line 5: This line of code has two errors
    • Strongly typed enumerations are strong on types and cannot be used directly.枚举值前必须加枚举类型
    • Strongly typed enumeration 不会进行隐式类型转换, so the enumeration value cannot be directly assigned to the int row variable (although the enumeration value of the strongly typed enumeration is integer by default, it cannot be used as an integer).
  • Line 6: Syntax error, strongly typed enumeration value is used as an integer, no implicit type conversion will be performed here
  • Line 7: The syntax is correct, the strongly typed enumeration value is cast before being compared with the integer.
  • Line 11: The printed result is 4, and the underlying type value of the strong type enumeration defaults to int, so the memory occupied is 4 bytes
  • Line 12: The printed result is 1, indicating that the type of the enumeration value of the strong type is specified as char, so the memory size occupied is 1 byte, so that we can save more memory space.

2.2 Extensions to the original enumeration

Compared with the original enumeration, the strongly typed enumeration is more like a C++ enumeration. But in order to cooperate with the new enumeration type, C++11 also extends the original enumeration type:

The underlying type of the original enumeration type is still specified by the compiler by default. 但也可以跟强类型枚举类一样,显式地由程序员来指定. The way to specify it is the same as the strong type enumeration, adding: type after the enumeration name, where type can be any integer except wchar_t. For example:

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

Regarding scope, in C++11, the names of enumeration members are not only automatically output to the parent scope, but also valid within the scope defined by the enumeration type. for example:

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

The writing methods of lines 4 and 5 in the above program are legal.

These two extensions to the original enumeration type in C++11 retain backward compatibility, and it is also convenient for programmers to operate two enumeration types at the same time in the code. In addition, we can also use the keyword enum struct when declaring a strongly typed enumeration. Real 际上 enum struct 和 enum class 在语法上没有任何区别(the members of enum class are not divided into public and private, and templates will not be used to support generalized declarations).

Guess you like

Origin blog.csdn.net/weixin_38346042/article/details/131373482