天天看点

【Cpp】C++的enum

一、继承C语言的enum

C++中的枚举是直接从C语言中继承过来的,在这过程中,也做了改进。如C语言中定义一个枚举类型的变量必须加上enum

enum QuarterFirst{JAN, FEB, MAR};//定义类型QuarterFirst
    enum QuarterFirst quarter1 = JAN;//定义QuarterFirst类型的变量quarter1
           

这在定义变量时显得臃肿,C语言都是通过typedef解决的

typedef enum QuarterFirst{JAN, FEB, MAR} QF;
    QF quarter1 = JAN;
           

而在C++中,定义变量时可以省略关键字enum

enum QuarterFirst{JAN, FEB, MAR};//定义类型QuarterFirst
    QuarterFirst quarter1 = JAN;//C++中是合法的
           

但是,早期的C++也存在以下缺陷未进行修补:

  1. 两个不同的枚举,他们枚举列表中的标识符的作用范围是全局的,不能重复,如以下定义是错误的:
enum Month {JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC};
    enum QuarterFirst{JAN, FEB, MAR};
           
  1. 默认向整型隐式转换,这导致逻辑错误的东西在理论层面成立
#include <iostream>
enum QuarterFirst{JAN, FEB, MAR};
enum WEEK{MON, TUE, WEN};
int main(void)
{
    QuarterFirst quarter1 = JAN;
    WEEK week1 = MON;
    std::cout << (quarter1 == week1 ? "YES" : "NO") << std::endl;
    return 0;
}
           
【Cpp】C++的enum

虽然说

MON

JAN

是两个不同类型,但是在警告之后还是转换成了整型0进行比较,所以结果是

YES

  1. 无视底层的数据类型,如我们定义

    enum WEEK{MON, TUE, WEN = 0xffffffffU};

    WEN

    G++

    MSVC

    下的结果分别如下:
【Cpp】C++的enum
【Cpp】C++的enum

二、C++的解决方案

enum

放入

class

中,默认里面的标识符都是私有的

同时还可以进行成员标识符默认类型的定义

这就相当于给了每个类型一个独立的命名空间,在访问里面的标识符时需要在前面加上类型的名称:

EnumType::Member1

测试代码:

#include <iostream>

enum class Month{JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC};
enum class QuarterFirst:unsigned int{JAN, FEB, MAR};
enum class WEEK:unsigned int{MON, TUE, WEN};

int main(void)
{
    QuarterFirst quarter1 = QuarterFirst::JAN;
    WEEK week1 = WEEK::MON;
    std::cout << (quarter1 == week1 ? "YES" : "NO") << std::endl;
    return 0;
}
           

如图所示,编译器在

quarter1 == week1

处进行了报错;并且尽管

Month

QuarterFirst

里面有一样的标识符,也未报错

【Cpp】C++的enum

继续阅读