【转】C++ 枚举类型的思考
转自: http://blog.csdn.net/classfactory/article/details/87749
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++ 枚举类型的思考的更多相关文章
- java 枚举类型和数据二进制等问题思考
.以下代码的输出结果是什么? int X=100; int Y=200; System.out.println("X+Y="+X+Y); System.out.println(X+ ...
- Spring mvc 接口枚举类型数据格式化处理
一.背景简述 首先,我们都知道枚举实例有两个默认属性,name 和 ordinal,可通过 name()和ordinal()方法分别获得.其中 name 为枚举字面量(如 MALE,FEMALE),o ...
- Java枚举类型enum使用详解
java的Enum枚举类型终于在j2se1.5出现了.之前觉得它只不过是鸡肋而已,可有可无.毕竟这么多年来,没有它,大家不都过得很好吗?今日看<Thinking in Java>4th ...
- Enum枚举类型实战总结,保证有用!
一般在我们开发时如果能使用枚举罗列的,一般都会定义一个枚举类型.将枚举类型作为方法的参数,可以方便的进行调用,给我们带来不少的遍历,当然有时候它还不如直接用一个int类型带来,带来一定灵活性.但只要能 ...
- Asp.Net 将枚举类型(enum)绑定到ListControl(DropDownList)控件
在开发过程中一些状态的表示使用到枚举类型,那么如何将枚举类型直接绑定到ListControl(DropDownList)是本次的主题,废话不多说了,直接代码: 首先看工具类代码: /// <su ...
- golang枚举类型 - iota用法拾遗
在c#.java等高级语言中,经常会用到枚举类型来表示状态等.在golang中并没有枚举类型,如何实现枚举呢?首先从枚举的概念入手. 1.枚举类型定义 从百度百科查询解释如下:http://baike ...
- 第三条:用私有构造器或者枚举类型强化Singleton属性
1.使用单元素的枚举类型 public enum Singleton implements Serializable { INSTANCE; private String field; public ...
- 在WPF中使用变通方法实现枚举类型的XAML绑定
问题缘起 WPF的分层结构为编程带来了极大便利,XAML绑定是其最主要的特征.在使用绑定的过程中,大家都普遍的发现枚举成员的绑定是个问题.一般来说,枚举绑定多出现于与ComboBox配合的情况,此时我 ...
- 窥探Swift之别样的枚举类型
想必写过程序的童鞋对枚举类型并不陌生吧,使用枚举类型的好处是多多的,在这儿就不做过多的赘述了.Fundation框架和UIKit中的枚举更是数不胜数,枚举可以使你的代码更易阅读并且可以提高可维护性.在 ...
随机推荐
- leetCode题解之Contains Duplicate
1.题目描述 2.题目分析 直接使用hashTable 计数,超过1 则返回true,最后返回 false即可. 3.代码 bool containsDuplicate(vector<int&g ...
- 无锁HashMap的原理与实现
转载自: http://coolshell.cn/articles/9703.html 在<疫苗:Java HashMap的死循环>中,我们看到,java.util.HashMap并不能直 ...
- 使用 Azure CLI 管理 Azure 虚拟网络和 Linux 虚拟机
Azure 虚拟机使用 Azure 网络进行内部和外部网络通信. 本教程将指导读者部署两个虚拟机,并为这些 VM 配置 Azure 网络. 本教程中的示例假设 VM 将要托管包含数据库后端的 Web ...
- MySQL->>innodb_autoinc_lock_mode参数控制auto_increment 插入数据时相关锁的模式
转自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/15498/viewspace-2141640/ ---------------------------------- ...
- npm run dev时报错“events.js:160 throw er; // Unhandled 'error' event”
经查,此问题由端口占用导致,node服务器默认端口8080已被其他程序占用,关闭占用端口的程序或者修改node服务器的默认端口即可解决此问题
- 读取Execl表数据 导入数据库
不知不觉博客园园林都两年多了,我是今年毕业的应届生,最近公司项目需要改动,很多的数据需要导入,很多的实体类需要些.考虑到这些问题自己写了两个winform版的小工具,一个是读取Execl数据导入数据库 ...
- Python学习---Django关于POST的请求解析源码分析
当有请求到来之后,先判断请求头content_type是不是[application/x-www-form-urlencoded] --> 如果是则将请求数据赋值给request.body然后解 ...
- 单纯形算法 matlab
%单纯形 %目标函数标准化 % min x1-3x2+2x3 %输入参量 N=[3 -1 2;-2 4 0;-4 3 8]; B=eye(3); A=[N B]; cn=[1;-3;2]; cb=ze ...
- terminal 总结
(1) Mac添加命令别名 切换到用户主目录 (2). 编辑或新建.bash_profile文件 (3). 添加别名 alias ll='ls -Alh' (4). 重载该配置文件 source .b ...
- foreach 计数
foreach(var item in list.Select((x, i) => new { x, i })){ User user = item.x; int Idx = ite ...