免费预览已结束,剩余1页可下载查看
下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
至从C语言开始enum类型就被作为用户自定义分类有限集合常量的方法被引入到了语言当中,而且一度成为C+中定义编译期常量的唯一方法(后来在类中引入了静态整型常量)。根据上面对enum类型的描述,有以下几个问题:1.到底enum所定义出来的类型是一个什么样的类型呢?2.作为一个用户自定义的类型其所占用的内存空间是多少呢?3.使用enum类型是否真的能够起到有限集合常量的边界约束呢?4.大家可能都知道enum类型和int类型具有隐示(自动)转换的规则,那么是否真的在任何地方都可以使用enum类型的变量来代替int类型的变量呢? 1. 到底enum所定义出来的类型是一个什么样的类型呢? 在C+中大家都知道仅仅有两种大的类型分类:POD类型(注(1)和类类型。 enum所定义的类型其实属于POD类型,也就是说它会参与到POD类型的隐示转换规则当中去,所以才会出现enum类型与int类型之间的隐示转换现象。 那么也就是说enum所定义的类型不具备名字空间限定能力(因为不属于类类型),其所定义的常量子具备和enum类型所在名字空间相同的可见性,由于自身没有名字限定能力,所以会出现名字冲突现象。 如: struct CEType enum EType1 e1, e2 ; enum EType2 e1, e2 ; ; 上面的例子会出现e1、e2名字冲突编译时错误,原因就在于枚举子(e1、e2)是CEType名字空间中的名字,同样在引用该CEType中的枚举子时必须采用CEType:e1这样的方式进行,而不是CEType:EType1:e1来进行引用。 注(1)POD类型: 你可以将 POD 类型看作是一种来自外太空的用绿色保护层包装的数据类型,POD 意为“Plain Old Data”(译者:如果一定要译成中文,那就叫“彻头彻尾的老数据”怎么样!)这就是 POD 类型的含义。 其确切定义相当粗糙(参见 C+ ISO 标准),其基本意思是 POD 类型包含与 C 兼容的原始数据。 例如,结构和整型是 POD 类型,但带有构造函数或虚拟函数的类则不是。 POD 类型没有虚拟函数,基类,用户定义的构造函数,拷贝构造,赋值操作符或析构函数。 为了将 POD 类型概念化,你可以通过拷贝其比特来拷贝它们。此外, POD 类型可以是非初始化的。 2. 作为一个用户自定义的类型其所占用的内存空间是多少呢? 该问题就是sizeof( EType1 )等于多少的问题,是不是每一个用户自定义的枚举类型都具有相同的尺寸呢? 在大多数的32位编译器下(如:VC+、gcc等)一个枚举类型的尺寸其实就是一个sizeof( int )的大小,难道枚举类型的尺寸真的就应该是int类型的尺寸吗? 其实不是这样的,在C+标准文档(ISO14882)中并没有这样来定义, 标准中是这样说明的:“枚举类型的尺寸是以能够容纳最大枚举子的值的整数的尺寸”, 同时标准中也说名了:“枚举类型中的枚举子的值必须要能够用一个int类型表述”, 也就是说,枚举类型的尺寸不能够超过int类型的尺寸,但是是不是必须和int类型具有相同的尺寸呢? 上面的标准已经说得很清楚了,只要能够容纳最大的枚举子的值的整数就可以了,那么就是说可以是char、short和int。 例如: enum EType1 e1 = CHAR_MAX ; enum EType2 e2 = SHRT_MAX ; enum EType3 e3 = INT_MAX ; 上面的三个枚举类型分别可以用char、short、int的内存空间进行表示,也就是: sizeof( EType1 ) = sizeof( char ); sizeof( EType2 ) = sizeof( short ); sizeof( EType3 ) = sizeof( int ); 那为什么在32位的编译器下都会将上面三个枚举类型的尺寸编译成int类型的尺寸呢? 主要是从32位数据内存对其方面的要求进行考虑的,在某些计算机硬件环境下具有对齐的强制性要求(如:sun SPARC), 有些则是因为采用一个完整的32位字长CPU处理效率非常高的原因(如:IA32)。 所以不可以简单的假设枚举类型的尺寸就是int类型的尺寸,说不定会遇到一个编译器为了节约内存而采用上面的处理策略。 3. 使用enum类型是否真的能够起到有限集合常量的边界约束呢? 首先看一下下面这个例子: enum EType e1 = 0, e2 ; void func1( EType e ) if ( e = e1 ) / do something / do something because e != e1 must e = e2 void func2( EType e ) if ( e = e1 ) / do something else if ( e = e2 ) / do something func1( static_cast( 2 ) ); func2( static_cast( -1 ) ); 上面的代码应该很清楚的说明了这样一种异常的情况了,在使用一个操出范围的整型值调用func1函数时会导致函数采取不该采取的行为,而第二个函数可能会好一些他仅仅是忽略了超出范围的值。 这就说明枚举所定义的类型并不是一个真正强类型的有限常量集合,这样一种条件下和将上述的两个函数参数声明成为整数类型没有任何差异。所以以后要注意标准定义中枚举类型的陷阱。 (其实只有类类型才是真正的强类型) 4. 是否真的在任何地方都可以使用enum类型的变量来代替int类型的变量呢? 通过上面的讨论,其实枚举类型的变量和整型变量具有了太多的一致性和可互换性,那么是不是在每一个可以使用int类型的地方都可以很好的用枚举类型来替代呢? 其实也不是这样的,毕竟枚举类型是一个在编译时可区分的类型, 同时第2点的分析枚举类型不一定和int类型具有相同的尺寸,这两个差异就决定了在某些场合是不可以使用枚举类型来代替int类型的。 如: 第一种情况: enum EType e1 = 0, e2, e3 ; EType val; std:cin val; 第二种情况: enum EType e1 = 0, e2, e3 ; EType val; std:scanf( %d, &val ); 上面的两种情况看是基本上属于同一种类型的问题,其实不然。第一种情况会导致编译时错误, 会因为std:cin没有定义对应的枚举类型的重载运算符而出错,这就说明枚举类型是一种独立和鉴别的类型; 而第二种情况不会有任何编译时问题,但是可能会导致scanf函数栈被破坏而使得程序运行非法,为什么会这样呢? 上面已经分析过了枚举类型变量的尺寸不一定和int类型相同,这样一来我们采用%d就是说将枚举类型变量val当作4字节的int变量来看待并进行参数压栈, 而在某些编译器下sizeof( val )等于1字节,这样scanf函数就会将val变量地址中的后续的三字节地址也压入栈中, 并对其进行赋值,也许val变量后续的三个字节的地址没有特殊含义可以被改写(比如是字节对齐的空地址空间), 可能会认为他不会出现错误,其实不然,在scanf函数调用结束后会进行栈清理, 这样一来会导致scanf函数清理了过多的地址空间,从而破坏了外围函数的栈指针的指向,从而必然会导致程序运行时错误。由上面的说明枚举类型有那么多的缺点,那我们怎样才能够有一个类型安全的枚举类型呢?实际上,在最新的 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
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2024广告代理合同模板下载
- 2024女职工特殊权益保护专项集体合同公司女职工特殊权益保护专项集体合同
- 2024个人耐用消费品贷款合作合同范本
- 2024鸡场租赁合同
- 分期还款协议书样本
- 吉林省吉林市七年级上学期语文期中试卷2套【附答案】
- 2024商品购销合同书版范本
- 上海临时仓库租赁合同
- 音乐会场地租赁合同范本
- 标准汽车租赁合同样式
- 医学类-教学查房异位妊娠(宫外孕)
- 眼视光技术职业生涯规划大赛
- 《第八课 我的身体》参考课件
- 肥料创业计划书
- 信息通信网络运行管理员(高级)理论考试题库(学员用)
- 公司卷烟物流管理规范
- 报告医疗器械不良事件
- 物联网安全分析报告
- 黄芪对慢性疲劳综合征康复中的临床应用及相关机制探究
- 物业管理工作量化细则
- 2024市场营销学教师资格证试讲授课教案
评论
0/150
提交评论