C++ 中的枚举类型继承于 C 语言。就像其他从 C 语言继承过来的很多特性一样,C++ 枚举也有缺点,这其中最显著的莫过于作用域问题——在枚举类型中定义的常量,属于定义枚举的作用域,而不属于这个枚举类型。例如下面的示例:

enum FileAccess {
     Read = 0x1,
     Write = 0x2,
};

FileAccess access = ::Read; // 正确
FileAccess access = FileAccess::Read; // 错误

C++枚举的这个特点对于习惯面向对象和作用域概念的人来说是不可接受的。首先,FileAccess::Read 显然更加符合程序员的直觉,因为上面的枚举定义理应等价于如下的定义(实际上,.NET 中的枚举类型便是如此实现的):

class FileAccess {
     static const int Read = 0x1;
     static const int Write = 0x2;
};

其次,这导致我们无法在同一个作用域中定义两个同样名称的枚举值。也就是说,以下的代码是编译错误:

enum FileAccess {
     Read = 0x1,
     Write = 0x2,
};

enum FileShare {
     Read = 0x1, // 重定义
     Write = 0x2, // 重定义
};

如果这一点没有让你恼怒过的话,你可能还没写过多少 C++ 代码 :-)。实际上,在最新的 C++0x 标准草案中有关于枚举作用域问题的提案,但最终的解决方案会是怎样的就无法未卜先知了,毕竟对于象 C++ 这样使用广泛的语言来说,任何特性的增删和修改都必须十分小心谨慎。

当然,我们可以使用一些迂回的方法来解决这个问题(C++ 总是能给我们很多惊喜和意外)。例如,我们可以把枚举值放在一个结构里,并使用运算符重载来逼近枚举的特性:

struct FileAccess {
     enum __Enum {
         Read = 0x1,
         Write = 0x2
     };
     __Enum _value; // 枚举值

FileAccess(int value = 0) : _value((__Enum)value) {}
     FileAccess& operator=(int value) {
         this->_value = (__Enum)value;
         return *this;
     }
     operator int() const {
         return this->_value;
     }
};

我们现在可以按照希望的方式使用这个枚举类型:

FileAccess access = FileAccess::Read;

并且,因为我们提供了到 int 类型的转换运算符,因此在需要 int 的地方都可以使用它,例如 switch 语句:

switch (access) {
     case FileAccess::Read:
         break;
     case FileAccess::Write:
         break;
}

当然我们不愿意每次都手工编写这样的结构。通过使用宏,我们可以很容易做到这一点:

#define DECLARE_ENUM(E) \
struct E \
{ \
public: \
     E(int value = 0) : _value((__Enum)value) { \
     } \
     E& operator=(int value) { \
         this->_value = (__Enum)value; \
         return *this; \
     } \
     operator int() const { \
         return this->_value; \
     } \
\
     enum __Enum {

#define END_ENUM() \
     }; \
\
private: \
     __Enum _value; \
};

我们现在可以按如下的方式定义前面的枚举,并且不比直接写 enum 复杂多少。

DECLARE_ENUM(FileAccess)
     Read = 0x1,
     Write = 0x2,
END_ENUM()

DECLARE_ENUM(FileShare)
     Read = 0x1,
     Write = 0x2,
END_ENUM()

C++ 枚举类型的思考相关推荐

  1. 求你了,不要再在对外接口中使用枚举类型了!

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 最近,我们的线上环境出现了一个问题,线上代码在执行过程中抛 ...

  2. 为什么阿里巴巴RPC接口不允许使用枚举类型?

    点击上方 好好学java ,选择 星标 公众号 重磅资讯.干货,第一时间送达 今日推荐:今天给大家推荐 6 个 Spring Boot 项目,拿来就可以赚钱! 个人原创100W+访问量博客:点击前往, ...

  3. Java枚举类型(enum)详解

    文章目录 理解枚举类型 枚举的定义 枚举实现原理 枚举的常见方法 Enum抽象类常见方法 编译器生成的Values方法与ValueOf方法 枚举与Class对象 枚举的进阶用法 向enum类添加方法与 ...

  4. java previous_java – 在枚举类型上实现`next`和`previous`的最好方法是什么?

    假设我有一个枚举: enum E { A, B, C; } 如lucasmo by lucasmo所示,枚举值按照它们被初始化的顺序存储在静态数组中,您可以稍后用E.values()检索(克隆)此数组 ...

  5. 现代C++新特性 强枚举类型(PC浏览效果更佳)

    文字版PDF文档链接:现代C++新特性(文字版)-C++文档类资源-CSDN下载 1. 枚举类型的弊 C++之父本贾尼·斯特劳斯特卢普曾经在他的The Design And Evolution Of ...

  6. java枚举类构造方法默认是,枚举类型的构造方法_Java语言程

    枚举类型的构造方法_Java语言程 6.6.4 枚举类型的构造方法 枚举类型既然是类,那么就可以有构造方法.只不过只能是私有的(private),不能有公有的(public)构造方法,这是为了避免直接 ...

  7. 谈Java语言规范之枚举类型

    文章目录 枚举类型 一. 枚举常量 二.枚举主体声明 对枚举常数自我引用的限制: 三.枚举成员 这不是一顿快餐,希望你沉淀下来,细细品尝 写在前面 枚举类型可以考虑用来替换接口中的常量声明.并且 &l ...

  8. 《挑战30天C++入门极限》新手入门:C/C++中枚举类型(enum)

        新手入门:C/C++中枚举类型(enum) 如果一个变量你需要几种可能存在的值,那么就可以被定义成为枚举类型.之所以叫枚举就是说将变量或者叫对象可能存在的情况也可以说是可能的值一一例举出来. ...

  9. ASP.NET中绑定枚举类型

    在项目开发中好多地方用了枚举,要把枚举显示到下拉列表框中我们平常的方法就是在下拉列表控件中一个一个添加进去!这样做也行但如果我的枚举类型中的枚举值一旦改变,那么你就得满世界的去找然后再修改很麻烦. 这 ...

最新文章

  1. 关于正则表达式 g,m 参数的总结,为了回答“正则表达式(/[^0-9]/g,'')中的/g是什么意思?”...
  2. 【组队学习】【29期】6. 动手学数据分析
  3. light oj 1011Marriage Ceremonies
  4. php 开发商城 注意,php开发微商城要注意什么
  5. ACL 2019 | 基于知识增强的语言表示模型,多项NLP任务表现超越BERT
  6. MySQL 到PostgreSQL 的数据迁移工具
  7. Linux下Tomcat启动报错:port already in use
  8. 51C语言编译后执行到一半,“C语言” 读书札记之[再续编译执行]
  9. java微信第三方支付
  10. CentOS7.6下设置mysql服务开机启动
  11. BeanDefinition源码解析
  12. 程序员应该做的事(转自CSDN)
  13. ASP.NET 的服务器端控件有三种关于 ID 的属性 ID, ClientID 和 UniqueID
  14. sharepoint2010基于表单认证
  15. linux GSM0710(2)
  16. 安装SVN后,更新项目没有对号等图标
  17. 张小龙2019微信公开课演讲实录
  18. Jupyter Notebook切换conda虚拟环境
  19. 网络安全:为大家介绍5种常见的加密算法
  20. 矩阵的LU分解初步:一个对角线上元素非零的方阵

热门文章

  1. 大数据之-Hadoop3.x_MapReduce_MapTask源码解析---大数据之hadoop3.x工作笔记0126
  2. k8s核心技术-Pod(调度策略)_影响Pod调度(节点亲和性)---K8S_Google工作笔记0026
  3. 2012浙大878计算机专业基础综合大题答案解析
  4. C语言中宏定义和函数的取舍
  5. linux系统 mysql日志文件太大。造成数据库无法正常启动怎么解决
  6. 初试cocos2d-x坐标系
  7. ospf配置方法及相关问题
  8. 将多个集合合并成没有交集的集合
  9. 想成为编程高手,从基础做起
  10. java适配器有哪些_Java中适配器模式(Adapter)是什么? 适配器模式(详解)