it-swarm.com.de

Vererbung der Basis-Enum-Klasse

Gibt es ein Muster, in dem ich Enum von einem anderen Enum in C++ erben kann?

Sowas in der Art:

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


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

Nicht möglich. Es gibt keine Vererbung mit Aufzählungen. 

Sie können stattdessen Klassen mit benannten Konstanten verwenden.

Beispiel:

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;
};
57
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;
}
85
Mykola Golubyev

Sie können das nicht direkt tun, aber Sie könnten versuchen, die Lösung aus this article zu verwenden.

Die Hauptidee besteht darin, die Helper-Template-Klasse zu verwenden, die Aufzählungswerte enthält und den Typumwandlungsoperator aufweist. In Anbetracht dessen, dass der zugrunde liegende Typ für die Aufzählung int ist, können Sie diese Inhaberklasse nahtlos in Ihrem Code anstelle der Aufzählung verwenden.

10

Leider ist dies in C++ 14 nicht möglich. Ich hoffe, dass wir in C++ 17 eine solche Sprachfunktion haben werden. Da Sie für Ihr Problem bereits einige Problemumgehungen hatten, werde ich keine Lösung anbieten.

Ich möchte darauf hinweisen, dass die Formulierung "Erweiterung" und nicht "Vererbung" sein sollte. Die Erweiterung erlaubt mehr Werte (da Sie in Ihrem Beispiel von 3 auf 6 Werte springen), während Vererbung bedeutet, mehr Beschränkungen für eine gegebene Basisklasse festzulegen, sodass der Satz von Möglichkeiten kleiner wird. Daher würde ein potenzieller Guss der Vererbung genau entgegenwirken. Sie können abgeleitete Klassen in die Basisklasse umwandeln und nicht mit Klassenvererbung umgekehrt. Wenn Sie jedoch Erweiterungen haben, sollten Sie die Basisklasse "in die Erweiterung" umwandeln können und nicht umgekehrt. Ich sage "sollte", weil, wie gesagt, eine solche Sprachfunktion noch nicht existiert.

Wie wäre es damit? Ok Eine Instanz wird für jeden möglichen Wert erstellt, abgesehen davon ist sie sehr flexibel. Gibt es irgendwelche Nachteile?

.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;

Verwendungszweck:

BaseEnum e = DerivedEnum::THREE;

if (e == DerivedEnum::THREE) {
    std::cerr << "equal" << std::endl;
}
3
Dirk

Wie von bayda festgestellt, verfügt enum nicht (und sollte nicht) über Funktionalität verfügen. Daher habe ich folgende Vorgehensweise in Bezug auf Ihr Dilemma angenommen, indem ich die Antwort von Mykola Golubyev angepasst habe:

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

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

Wenn Sie enum in der abgeleiteten Klasse mit demselben Namen definieren und vom letzten Element des Korrespondenten enum in der Basisklasse starten, erhalten Sie fast das, was Sie möchten - geerbtes Enum . Schauen Sie sich diesen Code an:

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

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

Sie können ein Projekt SuperEnum verwenden, um erweiterbare Aufzählungen zu erstellen.

/*** 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
1
Dmitry Bravikov

Irgendwie hackig, aber das ist, was ich mir vorgestellt habe, wenn ich mich mit Scope-Enummen beschäftige:

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
};

und dann wie folgt verwenden:

OriginalType myOriginalType = (OriginalType)ExtendOriginalType::EXTENDED_BAR;
0
jsadler

Unmöglich.
Sie können die Aufzählung jedoch anonym in einer Klasse definieren und dann in abgeleiteten Klassen zusätzliche Aufzählungskonstanten hinzufügen.

0
bayda