La herencia de la clase Base enum

¿Hay un patrón donde puedo heredar enum de otra enumeración en C ++?

Algo como eso:

enum eBase { one=1, two, three }; enum eDerived: public eBase { four=4, five, six }; 

Imposible. No hay herencia con enums.

En su lugar, puede usar clases con const ints nombrados.

Ejemplo:

 class Colors { public: static const int RED = 1; static const int GREEN = 2; }; class RGB : public Colors { static const int BLUE = 10; }; class FourColors : public Colors { public: static const int ORANGE = 100; static const int PURPLE = 101; }; 
 #include  #include  class Enum { public: enum { One = 1, Two, Last }; }; class EnumDeriv : public Enum { public: enum { Three = Enum::Last, Four, Five }; }; int main() { std::cout < < EnumDeriv::One << std::endl; std::cout << EnumDeriv::Four << std::endl; return 0; } 

No puedes hacer eso directamente, pero podrías intentar usar la solución de este artículo.

La idea principal es usar la clase de plantilla auxiliar que tiene valores enum y tiene el operador de conversión de tipo. Teniendo en cuenta que el tipo subyacente para enum es int , puede usar esta clase de titular de manera transparente en su código en lugar de la enumeración.

Desafortunadamente no es posible en C ++ 14. Espero que tengamos esa función de lenguaje en C ++ 17. Como ya tiene algunas soluciones para su problema, no proporcionaré una solución.

Me gustaría señalar que la redacción debe ser “extensión” y no “herencia”. La extensión permite más valores (cuando saltas de 3 a 6 valores en tu ejemplo), mientras que la herencia significa poner más restricciones a una clase base dada, por lo que el conjunto de posibilidades se reduce. Por lo tanto, el casting potencial funcionaría exactamente en oposición a la herencia. Puede convertir la clase derivada a la clase base y no viceversa con la herencia de clase. Pero cuando tienes extensiones “deberías” poder convertir la clase base a su extensión y no viceversa. Estoy diciendo “debería” porque, como dije, esa característica de idioma todavía no existe.

¿Qué tal esto? Ok, se crea una instancia para cada valor posible, pero además de eso es muy flexible. ¿Hay algún inconveniente?

.h:

 class BaseEnum { public: static const BaseEnum ONE; static const BaseEnum TWO; bool operator==(const BaseEnum& other); protected: BaseEnum() : i(maxI++) {} const int i; static int maxI; }; class DerivedEnum : public BaseEnum { public: static const DerivedEnum THREE; }; 

.cpp:

 int BaseEnum::maxI = 0; bool BaseEnum::operator==(const BaseEnum& other) { return i == other.i; } const BaseEnum BaseEnum::ONE; const BaseEnum BaseEnum::TWO; const DerivedEnum DerivedEnum::THREE; 

Uso:

 BaseEnum e = DerivedEnum::THREE; if (e == DerivedEnum::THREE) { std::cerr < < "equal" << std::endl; } 

Bueno, si defines enum con el mismo nombre en la clase derivada y lo comienzas desde el último elemento de la enum correspondiente en la clase base, recibirás casi lo que deseas: enum heredado. Mira este código:

 class Base { public: enum ErrorType { GeneralError, NoMemory, FileNotFound, LastItem } } class Inherited: public Base { enum ErrorType { SocketError = Base::LastItem, NotEnoughBandwidth, } } 

Como dice bayda , las funciones de enum no tienen (y / o no deberían), así que he adoptado el siguiente enfoque a tu dilema mediante la adaptación de la respuesta de Mykola Golubyev :

 typedef struct { enum { ONE = 1, TWO, LAST }; }BaseEnum; typedef struct : public BaseEnum { enum { THREE = BaseEnum::LAST, FOUR, FIVE }; }DerivedEnum; 

Puede usar un proyecto SuperEnum para crear enumeraciones extensibles.

 /*** my_enum.h ***/ class MyEnum: public SuperEnum { public: MyEnum() {} explicit MyEnum(const int &value): SuperEnum(value) {} static const MyEnum element1; static const MyEnum element2; static const MyEnum element3; }; /*** my_enum.cpp ***/ const MyEnum MyEnum::element1(1); const MyEnum MyEnum::element2; const MyEnum MyEnum::element3; /*** my_enum2.h ***/ class MyEnum2: public MyEnum { public: MyEnum2() {} explicit MyEnum2(const int &value): MyEnum(value) {} static const MyEnum2 element4; static const MyEnum2 element5; }; /*** my_enum2.cpp ***/ const MyEnum2 MyEnum2::element4; const MyEnum2 MyEnum2::element5; /*** main.cpp ***/ std::cout < < MyEnum2::element3; // Output: 3 

Imposible.
Pero puede definir la enumeración anónimamente en una clase, luego agregar constantes de enumeración adicionales en las clases derivadas.