web-dev-qa-db-ja.com

基本列挙クラスの継承

C++の別の列挙型から列挙型を継承できるパターンはありますか??

そんな感じ:

enum eBase 
{
   one=1, two, three
};


enum eDerived: public eBase
{
   four=4, five, six
};
71
Sasha

ありえない。列挙型には継承がありません。

代わりに、名前付き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;
};
59
Brian R. Bondy
#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;
}
89
Mykola Golubyev

それを直接行うことはできませんが、 this の記事から解決策を試してみることができます。

主なアイデアは、列挙値を保持し、型キャスト演算子を持つヘルパーテンプレートクラスを使用することです。列挙型の基になる型はintであることを考慮すると、このホルダークラスを列挙型の代わりにコードでシームレスに使用できます。

10

残念ながら、C++ 14では不可能です。このような言語機能がC++ 17にあることを願っています。あなたはすでにあなたの問題に対するいくつかの回避策を持っているので、私は解決策を提供しません。

言い回しは「継承」ではなく「拡張」である必要があることを指摘したいと思います。拡張機能では、より多くの値を使用できます(この例では3から6の値にジャンプします)が、継承とは、与えられた基本クラスにより多くの制約を加えて、可能性のセットを縮小することです。したがって、潜在的なキャストは継承とまったく逆に機能します。クラス継承を使用して、派生クラスを基本クラスにキャストできます。逆も同様です。ただし、拡張機能を使用する場合は、基本クラスをその拡張機能にキャストする必要があります(その逆はできません)。私が言ったように、そのような言語機能はまだ存在しないため、「すべき」と言っています。

これはどう? Okすべての可能な値に対してインスタンスが作成されますが、それ以外にも非常に柔軟です。欠点はありますか?

。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;
}
4
Dirk

プロジェクト 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
2
Dmitry Bravikov

baydaで述べられているように、列挙型には機能がない(および/またはあるべきではない)ため、Mykola Golubyevの応答:

typedef struct
{
    enum
    {
        ONE = 1,
        TWO,
        LAST
    };
}BaseEnum;

typedef struct : public BaseEnum
{
    enum
    {
        THREE = BaseEnum::LAST,
        FOUR,
        FIVE
    };
}DerivedEnum;
2
vigilance

さて、派生クラスで同じ名前のenumを定義し、基本クラスの対応するenumの最後の項目から開始すると、ほぼ必要なもの(継承された列挙型)を受け取ります。このコードを見てください:

class Base
{
public:
enum ErrorType
  {
  GeneralError,
  NoMemory,
  FileNotFound,
  LastItem
  }
}

class Inherited: public Base
{
enum ErrorType
  {
  SocketError = Base::LastItem,
  NotEnoughBandwidth,
  }
}
2
Haspemulator

ちょっとハッキーですが、これはスコープ付き列挙型を扱う場合に私が思いついたものです:

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;
0
jsadler

不可能。
ただし、クラスで匿名で列挙型を定義し、派生クラスで追加の列挙型定数を追加できます。

0
bayda