C++语言中,对于一个枚举类型(enum),其成员值在所属枚举类型的声明作用域内是不可重复的。这个继承自C语言的特性,使我在写程序时碰到有相同名称的枚举成员时,苦于寻找且方便易读的替代枚举名称。
这在C++程序开发方面带来了许多的不方便,在涉及枚举类型时必须时刻关注与现有的枚举变量是否有重名,在一定程度上限制了命名的自主性,也会降低程序的可读性。而在Visual Basic 6和.net系列语言中,两个不同的Enum类型可以具有相同的成员,在使用时只需加上Enum类型名称。目前就是要在C++中实现这种功能。
一个例子,用以描述一台计算机和一个音箱的类,它们都有一个状态属性State。音箱状态值只有开和关两种,而计算机状态还有休眠状态。由于休眠对于音箱没有任何意义,在严格要求的编码下,对于向音箱赋上休眠状态的无意义举动必须在编译时阻止,因此需在使此两种设备类的状态属性分别两个状态枚举类型,计算机状态和音箱状态,代码如下:
上述代码在编译时就不能通过,因为两个枚举的成员都是全局的,stateOpen和stateClosed都重复出现。因此,现在需要做的就是将这两个状态枚举类型分在两个作用域中声明,可采用的方式是在不同的namespace中声明或在不同的类中声明。
enumComputerState
...{
stateOpen,
stateClosed,
stateSuspended
};
enumSpeakerState
...{
stateOpen,
stateClosed
};
classComputer
...{
public:
voidSetState(ComputerStates)...{...}
};
在不同名称空间中声明枚举的代码如下:
namespacecomputer...{
enumComputerState
...{
stateOpen,
stateClosed,
stateSuspended
};
};
namespacespeaker...{
enumSpeakerState
...{
stateOpen,
stateClosed
};
};
usingnamespacecomputer;
usingnamespacespeaker;
classComputer
...{
public:
voidSetState(ComputerStates)
...{
if(s==computer::stateOpen)printf("StatesettoOpen ");
elseif(s==computer::stateClosed)printf("StatesettoClosed ");
elseif(s==computer::stateSuspended)
printf("StatesettoSuspended ");
}
};
虽然代码编译运行都通过,但在不同的名称空间中声明显然不是个好办法,一是Computer::SetState()方法中状态判断是,状态值(stateOpen等)前面并不是类型名称而是namespace名称。这样在代码可读性方面还是比较差。第二,就是有多少个enum类型,就得用多少个namespace以及using namespace,这在实际使用中是无法忍受的。因此, 目前只能是在class中声明enum类,将enum类型class化。代码修改如下:
classComputerState...{
public:
enum_ComputerState...{
stateOpen,
stateClosed,
stateSuspended
};
};
classSpeakerState...{
public:
enum_SpeakerState...{
stateOpen,
stateClosed
};
};
classComputer
...{
public:
voidSetState(ComputerState::_ComputerStates)
...{
if(s==ComputerState::stateOpen)
printf("StatesettoOpen ");
elseif(s==ComputerState::stateClosed)
printf("StatesettoClosed ");
elseif(s==ComputerState::stateSuspended)
printf("StatesettoSuspended ");
}
};
上述的每个Enum的作用域限制在一个类中,这样实现了不同enum类型其成员的重,但在使用时的类型表述上还没有统一。因此,根据枚举类型变量常用的几个操作符,对其做重载。代码如下:
classComputerState{
public:
enum_ComputerState{
stateOpen,
stateClosed,
stateSuspended
};
private:
_ComputerStatem_val;
public:
ComputerState():m_val(stateOpen){};
ComputerState(const_ComputerState&s):m_val(s){};
booloperator==(constComputerState&cs){
if(m_val==cs.m_val)returntrue;
elsereturnfalse;
}
operator_ComputerState(){returnm_val;}
};
classSpeakerState{
public:
enum_SpeakerState{
stateOpen,
stateClosed
};
private:
_SpeakerStatem_val;
public:
SpeakerState():m_val(stateOpen){};
SpeakerState(const_SpeakerState&s):m_val(s){};
booloperator==(constSpeakerState&cs){
if(m_val==cs.m_val)returntrue;
elsereturnfalse;
}
operator_ComputerState(){returnm_val;}
};
上述代码增加了类型值成员变量m_val、类复制构造函数,重载了枚举类的等于比较操作符和类型解包操作符,从而实现了一个枚举类型的类化,实现了枚举成员与枚举类自动组包和解包,在使用上,枚举的使用和VB里面除了"."与"::"在操作符上语言本身的区别外,基本相同。最重要的是在枚举成员在命名时不必因为有重名而使用可读性差的或者增加不必要的区别符号或名称。上述枚举类的使用时代码示例如下
classComputer
{
public:
voidSetState(ComputerStates)
{
if(s==ComputerState::stateOpen)printf("StatesettoOpen ");
elseif(s==ComputerState::stateClosed)printf("StatesettoClosed ");
elseif(s==ComputerState::stateSuspended)
printf("StatesettoSuspended ");
}
};
classSpeaker
{
public:
voidSetState(SpeakerStates)
{
if(s==SpeakerState::stateOpen)printf("StatesettoOpen ");
elseif(s==SpeakerState::stateClosed)printf("StatesettoClosed ");
}
};
intmain(intargc,char*argv[])
{
Computercpt;
Speakerspk;
ComputerStatecs=ComputerState::stateClosed;
SpeakerStatess=SpeakerState::stateOpen;
cpt.SetState(ComputerState::stateOpen);
spk.SetState(SpeakerState::stateOpen);
cpt.SetState(cs);
spk.SetState(ss);
returnEXIT_SUCCESS;
}
但是,由于enum的封装时增加了额外的构造函数和重载操作符,这部分代码将增加不少的工作量。为了减少这部分工作量,可以将这部分增加的函数定义成宏,如下:
#define ENUM_CLASS_DECLARE(cls_type, enum_type) /
public: enum_type m_val; /
public: /
cls_type ( const enum_type& s): m_val(s) {} ; /
bool operator == ( const enum_type& cs ) { /
if ( m_val == m_val ) return true; /
else return false; } /
operator enum_type() { return m_val; };
这样,上文的两个状态枚举类可以简化成下面的两个样子:
classComputerState{
public:
enum_ComputerState{
stateOpen,
stateClosed,
stateSuspended
};
ENUM_CLASS_DECLARE(ComputerState,_ComputerState)
};
classSpeakerState{
public:
enum_SpeakerState{
stateOpen,
stateClosed
};
ENUM_CLASS_DECLARE(SpeakerState,_SpeakerState)
};
到此为止,目的只是为了解决由于C++中枚举类型的成员变量的全局唯一性引起的在成员命名时的苦恼,一个简单的OPEN状态可能会用在许多不同的设备或其他多种事物对象的状态枚举中,解决此问题,其一就是一个OPEN状态对于不同的设备使用不同的名称,比如ComputerOpen、SpeakerOpen,其二是创建一个硕大无比的Enum类型,包含软件中涉及到的所有设备所有事物对象的状态,其三就是本文所说的枚举类型的类封装。
原文链接:http://read.newbooks.com.cn/info/135606.html
分享到:
相关推荐
Java SE程序 Enum枚举类Java SE程序 Enum枚举类Java SE程序 Enum枚举类Java SE程序 Enum枚举类Java SE程序 Enum枚举类Java SE程序 Enum枚举类Java SE程序 Enum枚举类Java SE程序 Enum枚举类Java SE程序 Enum枚举类...
C++中枚举类型(enum)
在C++中,枚举类型分为不限定作用域(enum)和限定作用域(enum class)。 2. enum与enum class的区别? (为什么需要限定作用域?) 答:枚举作用域是指枚举类型成员名字的作用域,起自其声明之处,终止枚举定义...
常见的enum类型重定义的解决方法,清晰明了。
资源分类:Python库 所属语言:Python 资源全名:aenum-2.0.1-py2-none-any.whl 资源来源:官方 安装方法:https://lanzao.blog.csdn.net/article/details/101784059
python中没有enum枚举类型,可能python认为这玩意压根就没用,下面列举了三种方法模拟enum枚举类型 方法1. 使用自定义类 class Numbers(object): ONE = 1 TWO = 2 THREE = 3 assert Numbers.ONE == 1 assert ...
java中enum枚举的详细用法。 0.0
以下几种方法来模拟enum:(感觉方法一简单实用) 复制代码 代码如下: # way1 class Directions: up = 0 down = 1 left = 2 right =3 print Directions.down # way2 dirUp, dirDown, dirLeft, dirRight =...
NULL 博文链接:https://rensanning.iteye.com/blog/2013734
enum枚举的方法
C语言enum枚举类型解析共13页.pdf.zip
包含了关于枚举类的应用,以及枚举类和接口的组合应用,扩展映射关系。很有用的工具类。
enum day {Sun,Mon,Tue,Wed,Thu,Fri,Sat}; 默认情况下,枚举符的值从0开始,其后值总是前面一个+1。 即Sun=0,Mon=1,Tue=2,Wed=3,Thu=4,Fri=5,Sat=6 也可以自己定义数值,其后值总是前面一个+1 例如: enum day {Sun=...
C++枚举类型 如果一个变量只有几种可能的值,可以定义为枚举(enumeration)类型。所谓“枚举”是指将变量的值一一列举出来,变量的值只能在列举出来的值的范围内。声明枚举类型用enum开头。例如: enum weekday{...
Java ---- enum --- 枚举类案例
C++枚举类型的简单实例,设置了enum result{win,lose,tie,cancle} 实现了这四种情况的顺序输出。
enum型也被成为枚举类型,它是一种可以将多个常量分组为一个并附加一系列值的类型,使用枚举定义的常量称为枚举器列表,默认情况下,枚举器从零开始按顺序编号。本篇文章给大家介绍关于JavaScript中枚举类型的使用。...
java enum详细教程。由浅入深,包括基本语法方面..很适合新手学习。/n各位看官。绝对超值。
ava enum 枚举的spring boot2.x完美实现demo源码。java的枚举类型,可以理解为一种特殊的java类