Есть ли шаблон, по которому я могу наследовать перечисление от другого перечисления в C ++?
Что-то такое:
enum eBase
{
one=1, two, three
};
enum eDerived: public eBase
{
four=4, five, six
};
Невозможно. С перечислениями наследования нет.
Вместо этого вы можете использовать классы с именами const ints.
Пример:
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;
};
Colors
экземпляры классов. Вы используете только значения int в статических константных членах.Color
, как вы могли бы дляenum
.#include <iostream> #include <ostream> 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; }
источник
int basic(EnumBase b) { return b; }
иint derived(EnumDeriv d) { return d; }
, эти типы не будут преобразованы вint
, хотя простые перечисления могут. И когда вы пытаетесь даже такой простой код , как этот:cout << basic(EnumBase::One) << endl;
, то вы получите сообщение об ошибке:conversion from ‘EnumBase::<anonymous enum>’ to non-scalar type ‘EnumBase’ requested
. Эти проблемы, вероятно, можно решить, добавив некоторые операторы преобразования.Вы не можете сделать это напрямую, но можете попробовать использовать решение из этой статьи.
Основная идея - использовать вспомогательный шаблонный класс, который содержит значения перечисления и имеет оператор приведения типа. Учитывая, что базовый тип для enum -
int
вы можете легко использовать этот класс-держатель в своем коде вместо enum.источник
К сожалению, в C ++ 14 это невозможно. Я надеюсь, что у нас будет такая языковая функция в C ++ 17. Поскольку у вас уже есть несколько способов решения вашей проблемы, я не буду предлагать решение.
Хочу отметить, что формулировка должна быть «расширение», а не «наследование». Расширение позволяет использовать больше значений (поскольку в вашем примере вы перескакиваете с 3 на 6 значений), тогда как наследование означает наложение большего количества ограничений на данный базовый класс, поэтому набор возможностей сокращается. Следовательно, потенциальное приведение будет работать прямо противоположно наследованию. Вы можете привести производный класс к базовому классу, а не наоборот с наследованием классов. Но при наличии расширений вы «должны» иметь возможность преобразовывать базовый класс в его расширение, а не наоборот. Я говорю «следует», потому что, как я уже сказал, такой языковой функции все еще не существует.
источник
extends
это ключевое слово для наследования в языке Eiffel.Как насчет этого? Хорошо, экземпляр создается для всех возможных значений, но, кроме того, он очень гибкий. Есть ли минусы?
.час:
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;
Применение:
BaseEnum e = DerivedEnum::THREE; if (e == DerivedEnum::THREE) { std::cerr << "equal" << std::endl; }
источник
BaseEnum::i
публичный иBaseEnum::maxI
приватный.Что ж, если вы определите
enum
с тем же именем в производном классе и запустите его с последнего элемента корреспондентаenum
в базовом классе, вы получите почти то, что хотите - унаследованное перечисление. Взгляните на этот код:class Base { public: enum ErrorType { GeneralError, NoMemory, FileNotFound, LastItem, }; }; class Inherited: public Base { public: enum ErrorType { SocketError = Base::LastItem, NotEnoughBandwidth, }; };
источник
Как указано
bayda
, перечисления не имеют (и / или не должны) иметь функциональность, поэтому я применил следующий подход к вашему затруднительному положению, адаптировавMykola Golubyev
ответ:typedef struct { enum { ONE = 1, TWO, LAST }; }BaseEnum; typedef struct : public BaseEnum { enum { THREE = BaseEnum::LAST, FOUR, FIVE }; }DerivedEnum;
источник
Вы можете использовать проект SuperEnum для создания расширяемых перечислений.
/*** my_enum.h ***/ class MyEnum: public SuperEnum<MyEnum> { 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
источник
const int&
простогоint
Вроде хакерство, но вот что я придумал, имея дело с перечислениями с областью видимости:
enum class OriginalType { FOO, // 0 BAR // 1 END // 2 }; enum class ExtendOriginalType : std::underlying_type_t<OriginalType> { EXTENDED_FOO = static_cast<std::underlying_type_t<OriginalType>> (OriginalType::END), // 2 EXTENDED_BAR // 3 };
а затем используйте как:
источник
Этот ответ является вариантом ответа Брайана Р. Бонди. Поскольку был запрошен в комментарии, я добавляю его в качестве ответа. Я не говорю о том, действительно ли это того стоит.
#include <iostream> class Colors { public: static Colors RED; static Colors GREEN; operator int(){ return value; } operator int() const{ return value; } protected: Colors(int v) : value{v}{} private: int value; }; Colors Colors::RED{1}; Colors Colors::GREEN{2}; class RGB : public Colors { public: static RGB BLUE; private: RGB(int v) : Colors(v){} }; RGB RGB::BLUE{10}; int main () { std::cout << Colors::RED << " " << RGB::RED << std::endl; }
Жить в Колиру
источник
Невозможно.
Но вы можете определить перечисление анонимно в классе, а затем добавить дополнительные константы перечисления в производные классы.
источник
enum xx { ONE = 1, TWO, xx_Done }; enum yy { THREE = xx_Done, FOUR, }; typedef int myenum; static map<myenum,string>& mymap() { static map<myenum,string> statmap; statmap[ONE] = "One"; statmap[TWO] = "Two"; statmap[THREE] = "Three"; statmap[FOUR] = "Four"; return statmap; }
Применение:
std::string s1 = mamap()[ONE]; std::string s4 = mymap()[FOUR];
источник