C ++의 다른 열거 형에서 열거 형을 상속 할 수있는 패턴이 있습니까 ??
그런 것 :
enum eBase
{
one=1, two, three
};
enum eDerived: public eBase
{
four=4, five, six
};
답변:
불가능합니다. 열거 형에는 상속이 없습니다.
대신 명명 된 const int가있는 클래스를 사용할 수 있습니다.
예:
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
클래스 인스턴스를 사용하지 않습니다 . 정적 const 멤버에서만 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 값을 보유하고 유형 캐스트 연산자를 갖는 도우미 템플릿 클래스를 사용하는 것입니다. enum의 기본 유형이 enum 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;
이 답변은 Brian R. Bondy 답변의 변형입니다. 댓글에서 요청되었으므로 답변으로 추가하고 있습니다. 그래도 정말 가치가 있는지 지적하지 않습니다.
#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];