扩展C+中的枚举+;? 在C++中有没有一种方法可以扩展/继承“枚举”?< /p>

扩展C+中的枚举+;? 在C++中有没有一种方法可以扩展/继承“枚举”?< /p>,c++,enums,C++,Enums,即: 或者至少定义它们之间的转换?以下代码运行良好 enum Enum {A,B,C}; enum EnumEx {D=C+1,E,F}; 如果您能够创建枚举的子类,那么它必须以另一种方式工作 子类中的实例集是超类中实例的子集。考虑一下标准的“形状”示例。Shape类表示所有形状的集合。Circle类及其子类表示圆形形状的子集 因此,为了保持一致,枚举的子类必须包含它继承自的枚举中元素的子集 (也不,C++不支持这个)。 < P>不,没有。 《C++》中的代码> > EnUM 真的是很糟糕的事

即:


或者至少定义它们之间的转换?

以下代码运行良好

enum Enum {A,B,C};
enum EnumEx {D=C+1,E,F};

如果您能够创建枚举的子类,那么它必须以另一种方式工作

子类中的实例集是超类中实例的子集。考虑一下标准的“形状”示例。Shape类表示所有形状的集合。Circle类及其子类表示圆形形状的子集

因此,为了保持一致,枚举的子类必须包含它继承自的枚举中元素的子集

(也不,C++不支持这个)。

< P>不,没有。

《C++》中的代码> > EnUM <代码>真的是很糟糕的事情,当然这是不幸的。

甚至C++0x中引入的
类enum
也没有解决这个扩展性问题(尽管它们至少为类型安全做了一些事情)

enum
的唯一优点是它们不存在:它们提供了某种类型安全性,同时不会造成任何运行时开销,因为编译器会直接替换它们

如果你想要这样一头野兽,你必须自己动手:

  • 创建一个包含int(基本上)的类
  • 为每个感兴趣的值创建命名构造函数
您现在可以随意扩展类(添加命名构造函数)


不过这是一个解决办法,我从未找到一种令人满意的方法来处理枚举…

我用这种方法解决了:

typedef enum
{
    #include "NetProtocols.def"
} eNetProtocols, eNP;
当然,如果在NetProtocols.def文件中添加新的网络协议,则必须重新编译,但至少它是可扩展的

“NetProtocols.def”将仅包含字段名:

HTTP,
HTTPS,
FTP
查看创建扩展枚举的方法。

只是一个想法:

您可以尝试为每个常量创建一个空类(可能将它们都放在同一个文件中以减少混乱),为每个类创建一个实例,并使用指向这些实例的指针作为“常量”。这样,编译器将理解继承,并在使用函数调用时执行任何必要的ChildPointer到ParentPointer的转换,并且编译器仍会进行类型安全检查,以确保没有人向函数传递无效的int值(如果使用最后一个value方法“扩展”枚举,则必须使用该方法)

不过,我还没有充分考虑到这一点,所以欢迎对这种方法发表任何评论


我会在我有一段时间之后,发布一个我的意思的例子。

< P>一个简单但有用的C++间隙的解决方法可以如下:

#define ENUM_BASE_VALS A,B,C
enum Enum {ENUM_BASE_VALS};
enum EnumEx {ENUM_BASE_VALS, D,E,F};

在我设计的一些小型硬件设备上运行的项目中,我遇到了这个问题。有一个包含许多服务的公共项目。其中一些服务使用枚举作为参数,以获得额外的类型检查和安全性。我需要能够在使用这些服务的项目中扩展这些枚举

正如其他人提到的,C++不允许你扩展枚举。但是,您可以使用具有枚举类所有优点的命名空间和模板来模拟枚举

枚举类具有以下优点:

  • 转换为已知的整数类型
  • 是一种值类型
  • 默认情况下是constexpr,在小型处理器上不占用任何有价值的RAM
  • 由enum::value限定范围并可访问
  • 在案例陈述中起作用
  • 当用作参数且需要显式强制转换时,提供类型安全性
  • 现在,如果将类定义为枚举,则无法在类声明中创建枚举的constexpr实例,因为该类尚未完成,并且会导致编译错误。此外,即使这样做有效,您也无法在以后的另一个文件/子项目中轻松扩展枚举的值集

    现在名称空间没有这样的问题,但它们不提供类型安全性

    答案是首先创建一个模板基类,它允许不同基类大小的枚举,这样我们就不会浪费我们不使用的东西

    template <typename TYPE>
    class EnumClass {
      private:
        TYPE value_;
      public:
        explicit constexpr EnumClass(TYPE value) :
            value_(value){
        }
        constexpr EnumClass() = default;
        ~EnumClass() = default;
        constexpr explicit EnumClass(const EnumClass &) = default;
        constexpr EnumClass &operator=(const EnumClass &) = default;
    
        constexpr operator TYPE() const {return    value_;}
        constexpr TYPE value() const {return value_;}
    
    };
    
    模板
    类枚举类{
    私人:
    类型值;
    公众:
    显式constexpr枚举类(类型值):
    价值(价值){
    }
    constexpr EnumClass()=默认值;
    ~EnumClass()=默认值;
    constexpr explicit EnumClass(const EnumClass&)=默认值;
    constexpr EnumClass&运算符=(const EnumClass&)=默认值;
    constexpr运算符类型()const{返回值}
    constexpr TYPE value()常量{返回值}
    };
    
    然后,对于我们要扩展和模拟的每个枚举类,我们创建一个名称空间和一个类型,如下所示:

    namespace EnumName {
       class Type :public Enum<uint8_t> {
         public:
            explicit constexpr Type(uint8_t value): Enum<uint8_t>(value){}
            constexpr Enum() = default;
       }
       constexpr auto Value1 = Type(1); 
       constexpr auto Value2 = Type(2); 
       constexpr auto Value3 = Type(3); 
    }
    
    #include <iostream>
    
    void fn(EnumName::Type val){
        if( val != EnumName::Value1 ){
          std::cout << val;
        }
    }
    
    int main(){
      for( auto e :EnumName::Set){
        switch(e){
          case EnumName::Value1:  
            std::cout << "a";
            break;
          case EnumName::Value4:  
            std::cout << "b";
            break;
          default:
            fn(e);
        }
      }
    }
    
    名称空间枚举名{
    类类型:公共枚举{
    公众:
    显式constexpr类型(uint8_t值):枚举(值){}
    constexpr Enum()=默认值;
    }
    constexpr auto Value1=类型(1);
    constexpr auto Value2=类型(2);
    constexpr auto Value3=类型(3);
    }
    
    然后,在代码的后面部分,如果已包含原始枚举名,则可以执行以下操作:

       namespace EnumName {
           constexpr auto Value4 = Type(4U); 
           constexpr auto Value5 = Type(5U); 
           constexpr auto Value6 = Type(6U); 
    
           constexpr std::array<Type, 6U> Set = {Value1, Value2, Value3, Value4, Value5, Value6};
        }
    
    名称空间枚举名{
    constexpr自动值4=类型(4U);
    constexpr自动值5=类型(5U);
    constexpr自动值6=类型(6U);
    constexpr std::数组集={Value1,Value2,Value3,Value4,Value5,Value6};
    }
    
    现在可以像这样使用枚举:

    namespace EnumName {
       class Type :public Enum<uint8_t> {
         public:
            explicit constexpr Type(uint8_t value): Enum<uint8_t>(value){}
            constexpr Enum() = default;
       }
       constexpr auto Value1 = Type(1); 
       constexpr auto Value2 = Type(2); 
       constexpr auto Value3 = Type(3); 
    }
    
    #include <iostream>
    
    void fn(EnumName::Type val){
        if( val != EnumName::Value1 ){
          std::cout << val;
        }
    }
    
    int main(){
      for( auto e :EnumName::Set){
        switch(e){
          case EnumName::Value1:  
            std::cout << "a";
            break;
          case EnumName::Value4:  
            std::cout << "b";
            break;
          default:
            fn(e);
        }
      }
    }
    
    #包括
    void fn(EnumName::Type val){
    如果(val!=EnumName::Value1){
    
    std::cout实际上,您可以以一种循环的方式扩展枚举

    C++标准定义有效枚举值为所有类型的有效值,因此下面的是有效的C++(11 +)。它不是未定义的行为,但它非常讨厌——你已经被警告过了。

    #include <cstdint>
    
        enum Test1:unit8_t {
            Value1 =0,
            Value2 =1
        };
    
        constexpr auto Value3 = static_cast<Test1>(3);
        constexpr auto Value4 = static_cast<Test1>(4);
        constexpr auto Value5 = static_cast<Test1>(5);
    
    
    Test1 fn(Test1 val){
      switch(val){
        case Value1:
        case Value2:
        case Value3:
        case Value4:
           return Value1;
        case Value5:
           return Value5; 
      } 
    }
    
    int main(){
      return static_cast<uint8_t>(fn(Value5));
    } 
    
    #包括
    枚举测试1:unit8\t{
    值1=0,
    值2=1
    };
    constexpr auto Value3=static_cast(3);
    constexpr auto Value4=static_cast(4);
    constexpr auto Value5=static_cast(5);
    测试1 fn(测试1 val){