C++11之强枚举类型

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/lixiaogang_theanswer/article/details/80140522

1. 枚举定义回顾
     枚举类型是c/c++中的一个基本内置类型,从枚举的本意来说:就是定义一个类别,并且穷举同一类别下的个体以供代码中去使用。详细使用参考:[ C语言之枚举类型 ]


2. c++98中枚举存在缺陷
     在c/c++中的枚举类型存在这样的特点,无论是 具名(有名字)的enum类型的名字 还是 枚举类型中的成员 都是全局范围的,其作用域是全局的。因此这会带来一系列无法事先控制的问题,在一个大型的项目以及系统开发中,可能会出现在不同的枚举中定义了相同的枚举成员,这时会编译不通过。报错:redeclaration 重复声明

     下面示例代码1中,定义2个枚举类型,分别是ColorPeople,可以看到这2个enum类型中有着相同的成员yellow,这在c/c++编译是不能通过的.

/*************************************************************************                                                                                         
 * File Name: enum.cpp
 * Author:    The answer
 * Function:  Other        
 * Mail:      2412799512@qq.com 
 * Created Time: 2018年04月29日 星期日 00时47分33秒
 ************************************************************************/

#include<iostream>
using namespace std;

typedef enum 
{
    red,
    orange,
    yellow,
    green,
    blue,
    cyan,
    purple
}Color;		//该枚举类型Color表示颜色


typedef enum
{
    yellow,   /*和Color枚举类型中的成员同名*/
    black,    
    white
}People;	//该枚举类型表示人种类

int main(int argc,char **argv)
{

    return 0;
}

g++ enum.cpp -o app 报错,具体提示如下:(重复定义)

enum.cpp:26:5: error: redeclaration of ‘yellow’
     yellow,
     ^
enum.cpp:16:5: note: previous declaration ‘Color yellow’
     yellow,
     ^

缺陷(1)
     对于上面的enum类型成员全局作用域问题,可能会想到采用namespace来对其进行封装,使ColorPeople类型在不同的作用域空间中,但是若其中的一个命名空间namespace匿名,而且在进行判断时时候漏写了命名空间名,同样会编译出现。因为匿名的namespace中的所有的enum成员都会默认进行全局名字空间。

/*************************************************************************
 * File Name: enum.cpp
 * Author:    The answer
 * Function:  Other        
 * Mail:      2412799512@qq.com 
 * Created Time: 2018年04月29日 星期日 00时47分33秒
 ************************************************************************/

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
using namespace std;

namespace   //
{
    typedef enum 
    {
        red,
        orange,
     //   yellow,
        green,
        blue,
        cyan,
        purple
    }Color;
}

namespace T
{
    typedef enum
    {
        yellow,
        black,
        white
    }People;
}

int main(int argc,char **argv)
{
    T::People man = T::black;
    if(man == yellow) //编译报错  正确为 if(man == T::yellow)
    {
        fprintf(stderr,"This man is not a black race.\n");
        return -1;
    }

    return 0;
}

namespace貌似可以解决enum类型成员全局作用域问题,但是可以看出来,这是极其的不便,在大型项目和工程中,难免会出现遗漏现象,因此不可采取。

缺陷(2)
      c/c++中的enum被设计为常量数值的别名,因此总是可以隐式的转换为整形int,这在某些时候也是极其不利的.


3. c++11强enum类型
     为了解决c/c++中的enum类型的一系列缺点,比如:非强类型,允许隐式转换为int型,占用存储空间及符号性不确定。c++11引入了枚举类(又称为:强枚举类型strong-typed enum

语法格式:

enum class 类型名 {枚举值表}; 

如:enum class People{yellow,black,white};
//这样就成功的定义了一个强类型的枚举People。

注意:等价于 enum struct 类型名{枚举值表};enum class中的成员没有公有私有之分,也不会使用
模板来支持泛化的功能)

3.1 强类型的枚举优点

(1)强作用域:强类型的枚举成员的名称不会被输出到其父作用域空间;
(2)转换限制:强类型枚举成员的值不可以与int隐式的相互转换。
(3)可以指定底层类型。强类型枚举底层类型为int,但是也可以显示的指定底层类型。具体方法:在enum名称后面加:“:type”,其中type可以是除wchar_t以外的任何int,如下:

enum class People:type char{yellow,black,white};
//指定了People为基于char的强枚举类型。

示例3中详细说明强枚举的特点:

/*************************************************************************
 * File Name: strongTypeEnum.cpp
 * Author:    The answer
 * Function:  Other        
 * Mail:      2412799512@qq.com 
 * Created Time: 2018年04月29日 星期日 02时02分10秒
 ************************************************************************/

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
using namespace std;

enum class Color
{
    red,
    orange,
    yellow,
    green,
    blue,
    cyan,
    purple

};

enum class Apple
{
    green = 1,
    red,
};

int main(int argc,char **argv)
{
    enum Apple apple = Apple::green;
    apple = red; //编译失败,必须使用强类型名称; ‘red’ was not declared in this scope
    if(apple == Color::red) //编译失败,必须使用Apple::red; no match for ‘operator==’ (operand types are ‘Apple’ and ‘Color’)
    {
       printf("The color of apple is red.\n");
    }
    if(apple == Apple::red)	//编译通过
    {
        printf("The color of apple is red.\n");
    }

    if(apple > 1)   //编译失败,无法隐式转换为int类型;error: no match for ‘operator>’ (operand types are ‘Apple’ and ‘int’)
    {
        cout<<"apple is greater than 1."<<endl;
    }
    
    if((int)apple > 1)	//编译通过,显示的类型转换
    {
        cout<<"apple is greater than 1."<<endl;
    }
    return 0;
}

4 . c++11对enum类型进行了扩展

主要有2个:
(1)对于底层的基本类型;这个参考前面的“强类型的优点(3)
(2)对于其作用域的扩展。在c++11中,枚举成员的名字除了会自动输出到父作用域,也可以在枚举类型定义的作用域内有效。

示例4:

enum Color{red,yellow,green,black,white};
enum Color color = red;
color = yellow;
color = Color::yellow;
//yello 和Color::yellow这两种形式都是合法的

5 . c++11中匿名的强类型枚举
     疑问:若在程序中,声明了一个匿名的强枚举类型,应该怎么去使用?

示例5:

/*************************************************************************
 * File Name: noNameEnum.cpp
 * Author:    The answer
 * Function:  Other        
 * Mail:      2412799512@qq.com 
 * Created Time: 2018年04月29日 星期日 02时41分41秒
 ************************************************************************/

#include<iostream>
using namespace std;
enum class{red,yellow,green,black,white} color;
int main(int argc,char **argv)
{
    color = red;   
    //编译失败;‘red’ was not declared in this scope
    bool value = (color == color::red); 
    //编译失败; error: ‘color’ is not a class or namespace
    return 0;
}

通过上面的示例5代码可以得知:若声明 了一个匿名的强枚举类型和示例,我们是无法对其示例进行设置值或去进行比较的,因此官方建议:在使用enum class(强枚举类型)的时候,应该总是提供一个名字。












     
     
     
     
     
     




展开阅读全文

没有更多推荐了,返回首页