enum类型的本质论(续)——CEnumClass类型安全的枚举类型

                          CEnumClass—类型安全的枚举类型
    在前面的一篇文章《enum类型的本质》中非常详尽的讨论了C++中原生枚举类型的一些
本质特征(http://blog.csdn.net/zhangjinjing/archive/2009/05/14/4183133.aspx)。

在文章的结尾遗留了这样一个话题:
    由上面的说明枚举类型有那么多的缺点,那我们怎样才能够有一个类型安全的枚举类型呢?
同时也给出了解决这个问题的一个思想:
    其实可以采用类类型来模拟枚举类型的有限常量集合的概念,同时得到类型安全的好处。
    沿着上面所阐述的思想来看为了解决这个问题必须通过C++中的类类型来强化类型的鉴别
能力,避免出现枚举类型和默认的int的隐示自动转换。我们来看看下面的实现:

template<typename SubT>
class CEnumClass
{
public:
    friend bool operator==( const SubT &lhs, const SubT &rhs )
    {
        return lhs.value() == rhs.value();
    }
    friend bool operator!=( const SubT &lhs, const SubT &rhs )
    {
        return !( lhs == rhs );
    }

    int value() const { return m_value; }

protected:
    CEnumClass( int i ) : m_value( i ) {}
    CEnumClass( const CEnumClass &rhs ) : m_value( rhs.m_value ) {}
    CEnumClass &operator=( const CEnumClass &rhs ) { m_value = rhs.m_value; return *this; }

protected:
    int m_value;
};

    首先简单的说明一下这个类,CEnumClass是一个奇异递归模板,也就是说模板参数SubT
是CEnumClass<SubT>的子类,那么这样一来为了声明一个枚举类就必须要想下面这样:

EType.hpp

class EType : public CEnumClass<EType>
{
};

上面声明就完成了enum EType这样一个过程,但是一个枚举类型不仅仅只是有类型,其中还
包括了有限常量枚举子,那我们就需要在类声明中添加对应的枚举子的定义:

EType.hpp

class EType : public CEnumClass<EType>
{
public:
    static const EType e1;
    static const EType e2;
    static const EType e3;    
    
private:
    EType( int i );
};
================================================================================
EType.cpp

const EType EType::e1 = 0;
const EType EType::e2 = 1;
const EType EType::e3 = 2;

EType::EType( int i ) : CEnumClass<EType>( i )
{
}

有了上面的定义就完成了一个枚举类型的定义了,现在我们来分析一下这个类型是否真的能
够解决文章《enum类型的本质》中所提到的所有缺陷和陷阱,同时又不失为真正的枚举含义。

1. 有限常量集合
   由于EType类的构造函数是私有的,所以无法在class声明之外定义任何类的实例,所以
所有的类实例必须在class声明中定义,有限性得到满足。常量属性可以通过是否能够修改
实例的内容来进行判断,这里没有任何办法可以修改枚举子e1、e2、e3中的内容,因为他
们本身是const属性,同时其成员均是外部不可访问的。

2. 尺寸大小
   分析一下这个类就可以很清楚的判断出sizeof( EType ) == sizeof( int ),尺寸固定
成为一个int类型的大小,不再是可以随着其取值范围变化的了,同时也没有占用任何额外
的空间,空间利用率非常高效。

3. 边界约束
   如果要定义一个枚举类型的变量,就必须像下面这样子:
EType val1 = EType::e1;
EType val2 = EType::e2;
EType val3 = EType::e3;
你不可能像下面这样子:
EType val1;
EType val2 = 1;
EType val2 = 100;
也就是说一个枚举变量的初始值必须在集合范围之内,不可能越过这个范围,也不可能取随
机值。

4. 代替int类型
   文章《enum类型的本质》中也明确的讨论了enum类型不能在任何情况下替代int类型,而
在这里只要通过value函数调用就可以返回对应的int值,不就可以替代int类型了么。也就
是像这样:
int i = val1.value();
这种做法是显示的,你现在知道你自己在干什么,而不是编译器隐示为你完成的。

    对于其他剩余的内容,比如比较、输入输出等大家可以自行练习完成,这里就不论述了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值