C++ 枚举类型的思考

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()

时间: 2024-09-14 14:33:19

C++ 枚举类型的思考的相关文章

高阶Java-Java枚举类型enum应用详解

java的Enum枚举类型终于在j2se1.5出现了.之前觉得它只不过是鸡肋而已,可有可无.毕竟这么多年来,没有它,大家不都过得很好吗?今日看<Thinking in Java>4th edition,里面有一句话"有时恰恰因为它,你才能够"优雅而干净"地解决问题.优雅与清晰很重要,正式它们区别了成功的解决方案与失败的解决方案.而失败的解决方案就是因为其他人无法理他."使用Enum枚举类型,可以将以前笨拙的代码变得优雅简单?但是,我同时也在思考另外一个问

2013级C++第1周(春)项目——枚举类型与结构体初步

课程主页在:http://blog.csdn.net/sxhelijian/article/details/11890759 [项目0-闲谈几点] 学习信息技术的大学生,在初接触行业,就能够进入到专业社区,有机会了解行业最新进展.享受海量资源.接触专业人士.获得实践机会,也给自己创造了一个全新.开放的展示空间,我们可以拥抱这样的机会. 与互联网相关的大学生,学习程序设计课程过程中,就同互联网亲密接触,学会驾驭,学会融入,各种观念,乃至于技术会逐渐深入.在进一步的学习过程中,博客.搜索.论坛.Em

EMF介绍系列(四、枚举类型、自定义类型和Map)

除了普通的类(接口)以外,在类图里可以定义一些特殊的元素,比较常见的是枚举类型 .自定义类型,它们对于一个完整可用的模型也是必不可少的,这篇帖子主要介绍EMF里它们 的使用方法.另外,由于EMF对Map的支持比较特别,所以在这里也简要介绍一下Map类型的定 义方法. 枚举类型 继续前面帖子的例子,现在要为产品增加一个评分属性,评分值可以是好中差之一,像这 样属性值只能是有限几个值之一的属性就应该定义为枚举类型(Enumeration).在类图里首 先创建一个名为Score的枚举类型,然后为它增加

ASP.NET中绑定枚举类型

asp.net 在项目开发中好多地方用了枚举,要把枚举显示到下拉列表框中我们平常的方法就是在下拉列表控件中一个一个添加进去!这样做也行但如果我的枚举类型中的枚举值一旦改变,那么你就得满世界的去找然后再修改很麻烦. 这里我有反射动态的绑定枚举值就可以很方便的做修改了,代码如下: public enum Eume{ 星期一, 星期二, 星期三, 星期四, 星期五} 绑定方法: private void BinderDays(){ Type type = typeof(Eume); FieldInfo

第十三章 枚举类型与位标记[《.net框架程序设计》读书笔记]

.net框架|笔记|程序|设计 第十三章 枚举类型与位标记 一. 枚举类型 1. 使用枚举类型的理由: l 枚举类型是得程序更容易编写.阅读.维护,在代码中使用符号名称代替数字是程序设计的一贯主张. l 强类型的,便于类型检验 2. 注意事项: l 枚举类型继承自System.Enum,System.Enum又继承自System.ValurType l 枚举类型不能定义方法.属性.事件 l 枚举类型为常数而非只读字段,因此可能引入版本问题(见第八章的相关讨论) l 将枚举类型与引用它的类型定义在

枚举类型的用法

C# 语言规范 14.3 枚举成员枚举类型声明的体用于定义零个或多个枚举成员,这些成员是该枚举类型的命名常数.任意两个枚举成员不能具有相同的名称. enum-member-declarations:(枚举成员声明:) enum-member-declaration(枚举成员声明)enum-member-declarations , enum-member-declaration(枚举成员声明 , 枚举成员声明) enum-member-declaration:(枚举成员声明:) attribut

F#教程:枚举类型

F#中枚举类型的定义实例如下: type Season = | Spring = 1 | Summer = 2 | Autumn = 3 | Winter = 4 使用刚定义过的枚举类型的代码如下: let s = Season.Winter if s = Season.Winter then printfn "冬" else printfn "冬以外" 不过如下代码就会编译出错: if s = "Winter" then printfn &qu

Effective Java(3) 用私有构造器或者枚举类型强化Singleton属性

一.背景 所谓的Singleton是指仅仅被实例化一次的类,Singleton通常被用来代表那些本质上唯一的系统组件. 实现Singleton有以下三种方法: ①. 私有构造器,公有静态final域. ②. 私有构造器,公有静态工厂方法. ③. 单元素枚举类型(首选). 二.私有构造器,公有静态final域 public class Singleton1 { public static final Singleton1 INSTANCE = new Singleton1(); // 公有静态fi

C#的枚举类型

枚举(enum)实际上是为一组在逻辑上密不可分的整数值提供便于记忆的符号.比如,我们声明一个代表星期的枚举类型的变量: enum WeekDay     Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday } WeekDay day; 注意:结构是由不同类型的数据组成的一组新的数据类型,结构类型的变量的值是由各个成员的值组合而成的.而枚举则不同,枚举类型的变量在某一时刻只能取枚举中某一个元素的值.比如,day这个表示"星期"