37.强类型枚举

37.枚举-强类型枚举


37.1 知识点

普通枚举可能存在的问题

1. 命名冲突

多个枚举中存在同名枚举项,会引发命名冲突,并可能和全局变量产生冲突。例如,枚举中有一项叫 Test1,又有一个全局变量叫 Test1,打印 Test1 时会报错。

enum E_Test
{
    Test1,
    Test2,
};
// int Test1 = 1;

又或者另一个枚举中有一项叫 Test1 也会报错:

// enum E_Test2
// {
//     Test1,
//     Test2,
// };

2. 隐式转换为 int,不够安全

枚举类型可能会不小心和整数进行混合运算。通常情况下,枚举是不希望参与到计算中的,因为它们是用于处理状态或类型的。

int a = 1 + Test1;

3. 不同枚举类型之间可以进行比较

虽然不同类型的枚举可以进行比较,但逻辑上并不符合常规。例如,E_TestE_Test3 的比较是没有意义的:

enum E_Test3
{
    T1,
    T2,
};
// if (Test1 == T1)
// {
    
// }

4. 默认枚举项类型只能是 int,大材小用

枚举项默认使用 int 类型存储,可能存在空间浪费的情况。

强类型枚举

强类型枚举用于提升枚举的安全性。语法如下:

enum class 枚举名
{
    各枚举项...
};

进行枚举变量赋值时,指明枚举类型:

枚举类型 变量 = 枚举类型::枚举项

主要作用:

  1. 避免命名冲突

若多个枚举中有同名枚举项,强类型枚举能够避免冲突。

enum class E_Test1 : short
{
    Test1,
    Test2,
};
E_Test1 t = E_Test1::Test1;

enum class E_Test2 : long long
{
    Test1,
    Test2,
};
E_Test2 t2 = E_Test2::Test1;
  1. 强类型枚举无法隐式转换为 int,需要使用 static_cast<int> 进行显式转换

这可以避免不小心将枚举和整数混用。

// 强类型枚举无法隐式转换为 int
// int a = 1 + t; // 错误
cout << static_cast<int>(t) << endl; // 0
E_Test2 t2 = E_Test2::Test1;
cout << static_cast<int>(t2) << endl; // 0
  1. 禁止不同类型的枚举之间进行比较

强类型枚举可以禁止不同类型的枚举进行比较:

// 不同枚举不能直接比较
// if (t == t2)
// {
//   
// }
  1. 可以指定枚举的底层类型

通过在枚举类型后加冒号指定类型。默认情况下,枚举存储项的类型是 int,但可以指定为其他整型类型。

enum class E_Test33 : short
{
    Test1,
    Test2,
};
E_Test33 t33 = E_Test33::Test1;

enum class E_Test44 : long long
{
    Test1,
    Test2,
};
E_Test44 t44 = E_Test44::Test1;

示例:

//不会命名冲突了
E_Test1 t = E_Test1::Test1;
E_Test1 t3 = E_Test1::Test2;

//不能直接计算
//int a = 1 + t;

//强类型枚举不会隐式转换为int了 需要我们自己转换
cout << static_cast<int>(t) << endl;//0
E_Test2 t2 = E_Test2::Test1;
cout << static_cast<int>(t2) << endl;//0

//不同枚举不能直接比较
//if (t == t2)
//{

//}

//同类型枚举可以直接比较
if (t == t3)
{

}

//可以指定枚举的底层类型 在后面加冒号指定类型 查看一个枚举变量大小
cout << sizeof(t33) << endl;//2 short
cout << sizeof(t44) << endl;//8 long long

37.2 知识点代码

Lesson37_枚举_强类型枚举.cpp

#include <iostream>
using namespace std;

#pragma region 知识点一 普通枚举可能存在的问题

//1.命名冲突
//  多个枚举中存在同名枚举项,会引发命名冲突
//  会和全局变量产生冲突

//例如枚举中有一项叫Test1 又有一个全局变量叫Test1 打印Test1时会报错
enum E_Test
{
    Test1,
    Test2,
};
//int Test1 = 1;

//又或者另一个枚举中有一项叫Test1 也会报错
//enum E_Test2
//{
//    Test1,
//    Test2,
//};




//2.隐式转换为int,不够安全
//  可能会不小心和整数进行混合运算

//3.不同枚举类型之间可以产生比较
//  不太符合逻辑

//比如E_Test和E_Test3比较
enum E_Test3
{
    T1,
    T2,
};


//4.默认枚举项类型只能是int,大材小用了

#pragma endregion

#pragma region 知识点二 强类型枚举

//强类型枚举是用来提升枚举的安全性
//语法:
// enum class 枚举名
// {
//     各枚举项...
// };
//进行枚举变量赋值时 指明枚举类型
// 枚举类型 变量 = 枚举类型::枚举项


//主要作用:
//1.避免命名冲突
//  若多个枚举中有同名枚举项,会引发冲突
enum class E_Test1 : short
{
    Test1,
    Test2,
};
E_Test1 t = E_Test1::Test1;

enum class E_Test2 : long long
{
    Test1,
    Test2,
};
E_Test2 t2 = E_Test2::Test1;

//2.强类型枚举无法隐式转换为整型,需要使用 static_cast<int>(枚举值) 进行显示转换
//  可以避免不小心将枚举和整数混用

//3.可以禁止不同类型的枚举之间进行比较

//4.可以指定枚举的底层类型 在后面加冒号指定类型
//  不加默认枚举中存储的枚举项是int类型
//  我们可以利用强类型枚举指定其存储类型
//  但是必须是整型类型,不能是其他类型
enum class E_Test33 : short
{
    Test1,
    Test2,
};
E_Test33 t33 = E_Test33::Test1;

enum class E_Test44 : long long
{
    Test1,
    Test2,
};
E_Test44 t44 = E_Test44::Test1;

#pragma endregion

int main()
{
    std::cout << "强类型枚举\n";

    #pragma region 知识点一 普通枚举可能存在的问题

    //1.命名冲突
    //  多个枚举中存在同名枚举项,会引发命名冲突
    //  会和全局变量产生冲突
    //cout << Test1 << endl;//如果又重复定义Test1会报错

    //2.隐式转换为int,不够安全
    //可能会不小心和整数进行混合运算
    //枚举一般是不太希望它参与到计算当中
    //因为枚举是希望用于处理状态、类型的
    //int a = 1 + Test1;

    //3.不同枚举类型之间可以产生比较
    //  不太符合逻辑
    //不同类型的枚举虽然能够比较 但是逻辑上是不太合理的
    //因为 不同枚举之间代表的是不同的含义
    //比如E_Test和E_Test3比较
    /*if (Test1 == T1)
    {

    }*/

    #pragma endregion
    
    #pragma region 知识点二 强类型枚举

    //不会命名冲突了
    E_Test1 t = E_Test1::Test1;
    E_Test1 t3 = E_Test1::Test2;

    //不能直接计算
    //int a = 1 + t;

    //强类型枚举不会隐式转换为int了 需要我们自己转换
    cout << static_cast<int>(t) << endl;//0
    E_Test2 t2 = E_Test2::Test1;
    cout << static_cast<int>(t2) << endl;//0

    //不同枚举不能直接比较
    //if (t == t2)
    //{

    //}

    //同类型枚举可以直接比较
    if (t == t3)
    {

    }

    //可以指定枚举的底层类型 在后面加冒号指定类型 查看一个枚举变量大小
    cout << sizeof(t33) << endl;//2 short
    cout << sizeof(t44) << endl;//8 long long

    #pragma endregion
}

37.3 练习题

枚举和强类型枚举在语法上有什么区别?

普通枚举声明:

enum 枚举名
{
    枚举项, ..... , ...... , .... 
}

普通枚举变量声明:

枚举类型 变量名 = 枚举项名;

强类型枚举声明:

enum class 枚举名 : 整形类型 (可选)
{
    枚举项, ..... , ...... , ....
}

强类型枚举变量声明:

枚举类型 变量名 = 枚举类型::枚举项;

强类型枚举和普通枚举在使用上有什么区别?

  1. 声明方式不同

  2. 强类型枚举不存在普通枚举的命名冲突问题

  3. 强类型枚举不会像普通枚举一样隐式转换为int,需要用 static_cast<int>() 进行转换

  4. 强类型枚举不能彼此比较,普通枚举可以(但是不建议)

  5. 强类型枚举可以指定整形存储的类型,如果不指定会和普通枚举一样用int



转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com

×

喜欢就点赞,疼爱就打赏