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

  • 相关阅读:
    基于Linux平台的自动化运维Devops-----之自动化系统部署
    Centos7.1 mini版安装后安装图形界面教程
    python包管理之Pip安装及使用-1
    maven中jar、war、pom的区别
    黄焖鸡
    django-celery配置
    文档编写注意事项
    java时间处理,获取当前时间的小时,天,本周周几,本周周一的日期,本月一号的日期
    flink连接hbase方法及遇到的问题
    pycharm远程debug(内网环境,跳板机)
  • 原文地址:https://www.cnblogs.com/rollenholt/p/2405456.html
Copyright © 2020-2023  润新知