Наследование класса базового перечисления
есть шаблон, где я могу наследовать перечисление из другого enum в C++??
что-то вроде этого:
enum eBase
{
one=1, two, three
};
enum eDerived: public eBase
{
four=4, five, six
};
9 ответов:
Не возможно. Нет никакого наследования с перечислениями.
вместо этого вы можете использовать классы с именем 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; };
#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
вы можете легко использовать этот класс держателя в своем коде вместо перечисления.
к сожалению, это невозможно в C++14. Я надеюсь, у нас будет такая функция языка в C++17. Поскольку у вас уже есть несколько обходных путей для вашей проблемы, я не буду предоставлять решение.
Я хотел бы отметить, что формулировка должна быть "продолжением", а не "наследование". Расширение позволяет использовать больше значений (как вы прыгаете от 3 до 6 значений в вашем примере), тогда как наследование означает наложение большего количества ограничений на данный базовый класс, поэтому набор возможностей сокращается. Поэтому потенциальное литье будет работать прямо противоположно наследованию. Вы можете привести производный класс к базовому классу, а не наоборот с наследованием класса. Но при наличии расширений вы "должны" иметь возможность привести базовый класс к его расширению, а не наоборот. Я говорю "должен", потому что, как я уже сказал, такой языковой функции все еще не существует.
как насчет этого? ОК экземпляр создается для каждого возможного значения, но кроме того, его очень гибкий. Есть ли минусы?
.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;
использование:
BaseEnum e = DerivedEnum::THREE; if (e == DerivedEnum::THREE) { std::cerr << "equal" << std::endl; }
Ну, если ты определишь
enum
с тем же именем в производном классе и начать с последнего элемента корреспондентenum
в базовом классе, вы получите почти то, что вы хотите - в наследство перечисление. Посмотрите на этот код:class Base { public: enum ErrorType { GeneralError, NoMemory, FileNotFound, LastItem } } class Inherited: public Base { enum ErrorType { SocketError = Base::LastItem, NotEnoughBandwidth, } }
как заявил
bayda
, перечисления не имеют (и/или не должны) функциональности, поэтому я принял следующий подход к вашему затруднительному положению, адаптировав С: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