Чи існує шаблон, де я можу успадкувати enum від іншого переліку в C ++ ??
Щось таке:
enum eBase
{
one=1, two, three
};
enum eDerived: public eBase
{
four=4, five, six
};
Чи існує шаблон, де я можу успадкувати enum від іншого переліку в 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 лише у статичних членах const.
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
. Ці проблеми, можливо, можна подолати, додавши деякі оператори перетворення.
Ви не можете цього зробити безпосередньо, але спробуйте використати рішення з цієї статті.
Основна ідея полягає у використанні допоміжного класу шаблону, який містить значення перерахування та має оператор приведення типу. Враховуючи, що основним типом переліку є те, що int
ви можете використовувати цей клас власника безперешкодно у своєму коді замість переліку.
На жаль, це неможливо в C ++ 14. Сподіваюся, у нас буде така мовна функція в C ++ 17. Оскільки у вас вже є кілька обхідних шляхів вирішення вашої проблеми, я не буду надавати рішення.
Я хотів би зазначити, що формулювання повинно бути "продовження", а не "спадкування". Розширення дозволяє отримати більше значень (оскільки ви переходите від 3 до 6 значень у вашому прикладі), тоді як успадкування означає введення більшої кількості обмежень для даного базового класу, щоб набір можливостей скорочувався. Тому потенційний кастинг працював би прямо навпаки від успадкування. Ви можете передати похідний клас до базового класу, а не до вірша зі спадкуванням класу. Але, маючи розширення, ви "повинні" мати можливість передати базовий клас на його розширення, а не навпаки. Я кажу "повинен", оскільки, як я вже говорив, така функція мови все ще не існує.
extends
це ключове слово для успадкування на мові Ейфеля.
Як щодо цього? Добре, екземпляр створюється для кожного можливого значення, але крім цього дуже гнучкий. Чи є мінуси?
.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;
}
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
};
а потім використовувати як:
OriginalType myOriginalType = (OriginalType)ExtendOriginalType::EXTENDED_BAR;
Ця відповідь є варіантом відповіді Брайана Р. Бонді. Оскільки запит було зроблено в коментарі, я додаю його як відповідь. Я не вказую на те, чи справді це варто.
#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];