web-dev-qa-db-fra.com

Héritage de classe enum de base

Existe-t-il un modèle dans lequel je peux hériter d'énum d'un autre enum en C++?

Quelque chose comme ca:

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


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

Pas possible. Il n'y a pas d'héritage avec des enums. 

Vous pouvez plutôt utiliser des classes avec des noms nommés const.

Exemple:

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

Vous ne pouvez pas faire cela directement, mais vous pouvez essayer d'utiliser la solution de this article.

L'idée principale est d'utiliser la classe de modèle d'assistance qui contient les valeurs enum et possède l'opérateur de transtypage. Considérant que le type sous-jacent pour enum est int, vous pouvez utiliser cette classe de détenteurs de manière transparente dans votre code au lieu de l’énumération.

10

Malheureusement, ce n'est pas possible en C++ 14. J'espère que nous aurons une telle fonctionnalité de langage en C++ 17. Comme vous avez déjà quelques solutions de contournement à votre problème, je ne fournirai pas de solution.

Je tiens à souligner que le libellé devrait être "extension" et non "héritage". L'extension autorise plus de valeurs (comme vous passez de 3 à 6 valeurs dans votre exemple), tandis que l'héritage signifie plus de contraintes pour une classe de base donnée, de sorte que l'ensemble des possibilités se réduit. Par conséquent, le casting potentiel fonctionnerait exactement à l'opposé de l'héritage. Vous pouvez attribuer une classe dérivée à la classe de base et non un vice-vers avec héritage de classe. Mais quand vous avez des extensions, vous "devriez" pouvoir convertir la classe de base en son extension et non en vice-vers. Je dis "devrait" parce que, comme je l'ai dit, une telle fonctionnalité linguistique n'existe toujours pas.

Que dis-tu de ça? Ok une instance est créée pour chaque valeur possible, mais à part cela, elle est très flexible. Y a-t-il des inconvénients?

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

Utilisation:

BaseEnum e = DerivedEnum::THREE;

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

Comme indiqué par bayda, les enum n’ayant pas (et/ou ne devrait pas) de fonctionnalités, j’ai adopté l’approche suivante pour résoudre votre dilemme en adaptant la réponse de Mykola Golubyev:

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

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

Eh bien, si vous définissez enum avec le même nom dans la classe dérivée et le démarrez à partir du dernier élément de enum correspondant dans la classe de base, vous recevrez presque ce que vous voulez - une enumération héritée . Regardez ce code:

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

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

Vous pouvez utiliser un projet SuperEnum pour créer des énumérations extensibles.

/*** 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

C'est un peu le genre de hacky, mais c'est ce que j'ai proposé si je traite d'enums étendus:

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

et ensuite utiliser comme:

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

Impossible.
Mais vous pouvez définir l’énumération de manière anonyme dans une classe, puis ajouter des constantes d’énumération supplémentaires dans les classes dérivées.

0
bayda