Есть ли образец, где я могу наследовать перечисление от другого перечисления в C++??
Что-то вроде того:
enum eBase
{
one=1, two, three
};
enum eDerived: public eBase
{
four=4, five, six
};
Есть ли образец, где я могу наследовать перечисление от другого перечисления в C++??
Что-то вроде того:
enum eBase
{
one=1, two, three
};
enum eDerived: public eBase
{
four=4, five, six
};
Невозможно. Наследования с перечислениями нет.
Вместо этого вы можете использовать классы с named 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;
}
Вы не можете сделать это напрямую, но вы можете попробовать использовать решение из этой статьи.
Основная идея заключается в использовании вспомогательного класса шаблона, который содержит значения перечисления и имеет оператор приведения типа. Учитывая, что базовым типом для enum является int
вы можете без проблем использовать этот класс-держатель в своем коде вместо enum.
К сожалению, это невозможно в С++ 14. Надеюсь, у нас будет такая языковая функция в С++ 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
, перечисление не имеет функциональности (и/или не должно), поэтому я применил следующий подход к вашему затруднительному положению, адаптировав Mykola Golubyev
response:
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
невыполнима.
Но вы можете определить анонимное перечисление в классе, а затем добавить дополнительные константы перечисления в производные классы.
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];