C++强类型枚举

传统枚举类型的缺点

  • 非强类型作用域
    		enum Type { General, Light, Medium, Heavy };
    		enum Category { General, Pistol, MachineGun, Cannon };
    
    由于General都是全局的名字,因此编译会报错。
  • 允许隐式转换为整型
    #include 
    using namespace std;
    
    enum Type { General, Light, Medium, Heavy };
    // 无法编译通过,重复定义了General
    //enum Category { General, Pistol, MachineGun, Cannon };
    enum Category { Pistol, MachineGun, Cannon };
    
    struct Killer {
        Killer(Type t, Category c) : type(t), category(c){}
        Type type;
        Category category;
    };
    
    int main() {
        Killer cool(General, MachineGun);
        // ...
        // ...其它很多代码...
        // ...
        if (cool.type >= Pistol)
            cout << "It is not a pistol" << endl;
        // ...
        cout << is_pod::value << endl;        // 1
        cout << is_pod::value << endl;    // 1
    
        return 0;
    
  • 占用存储空间
    #include 
    using namespace std;
    
    class Type {
    public:
        enum type { general, light, medium, heavy };
        type val;
    public:
        Type(type t): val(t){}
        bool operator >= (const Type & t) { return val >= t.val; }
        static const Type General, Light, Medium, Heavy;
    }; 
    
    const Type Type::General(Type::general);
    const Type Type::Light(Type::light);
    const Type Type::Medium(Type::medium);
    const Type Type::Heavy(Type::heavy);
    
    class Category {
    public:
        enum category { pistol, machineGun, cannon };
        category val;
    public:
        Category(category c): val(c) {}
        bool operator >= (const Category & c) { return val >= c.val; }
        static const Category Pistol, MachineGun, Cannon;
    };
    
    const Category Category::Pistol(Category::pistol);
    const Category Category::MachineGun(Category::machineGun);
    const Category Category::Cannon(Category::cannon);
    
    struct Killer {
        Killer(Type t, Category c) : type(t), category(c){}
        Type type;
        Category category;
    };
    
    int main() {
        // 使用类型包装后的enum
        Killer notCool(Type::General, Category::MachineGun);
        // ...
        // ...其它很多代码...
        // ...
        if (notCool.type >= Type::General)   // 可以通过编译
            cout << "It is not general" << endl;
    #if 0
        if (notCool.type >= Category::Pistol)   // 该句无法编译通过
            cout << "It is not a pistol" << endl;
    #endif
        // ...
        cout << is_pod::value << endl;        // 0
        cout << is_pod::value << endl;    // 0
        return 0;
    }
    
  • 符号性不确定:标准规定,C++枚举类型所基于的“基础类型”是由编译器来具体指定实现的,这会导致枚举类型成员的基本类型的不确定性问题(尤其是符号性)
    #include 
    using namespace std;
    
    enum C { C1 = 1, C2 = 2};
    enum D { D1 = 1, D2 = 2, Dbig = 0xFFFFFFF0U };
    enum E { E1 = 1, E2 = 2, Ebig = 0xFFFFFFFFFLL};
    int main() {
        cout << sizeof(C1) << endl;   // 4
    
        cout << Dbig << endl;   // 编译器输出不同,GCC:4294967280, Visual C++输出-16
        cout << sizeof(D1) << endl;     // 4
        cout << sizeof(Dbig) << endl;   // 4
    
        cout << Ebig << endl;   // 68719476735
        cout << sizeof(E1) << endl; // 8
        return 0;
    }
    

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

enum class Type { General, Light, Medium, Heavy };

优势:

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

  • 转换限制,强类型枚举成员的值不可以与整型隐式地相互转换,但可以显示转换为其他类型;

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

      enum class Type : char { General, Light, Medium, Heavy };
    
  • Type同时是POD类型,几乎不带来任何额外的开销;

匿名的强类型枚举

enum class { General, Light, Medium, Heavy } weapon;
int main()
{
	weapon = General; // 无法编译通过
	bool b = (weapon == weapon::General); // 无法编译通过
	return 0;
}

我们声明了一个匿名的enum class实例weapon,却无法对其设置值或者比较其值,事实上,使用enum class的时候,应该总是为其提供一个名字。但可以通过decltype来获得匿名强类型枚举的类型并且进行使用(但这样做没什么太大的意义)。

你可能感兴趣的:(总结,C++11)