c++ - Declarar una enumeración dentro de una clase
class enums (5)
Si el
Color
es algo específico para soloCar
, entonces esa es la forma en que limitaría su alcance. Si va a tener otra Enum deColor
que usen otras clases, entonces también podría hacerlo global (o al menos fuera deCar
).No hace ninguna diferencia. Si hay uno global, el local se sigue utilizando de todos modos, ya que está más cerca del alcance actual. Tenga en cuenta que si define esas funciones fuera de la definición de clase, necesitará especificar explícitamente
Car::Color
en la interfaz de la función.
En el siguiente fragmento de código, la Enum de Color
se declara dentro de la clase Car
para limitar el alcance de la enumeración e intentar no "contaminar" el espacio de nombres global.
class Car
{
public:
enum Color
{
RED,
BLUE,
WHITE
};
void SetColor( Car::Color color )
{
_color = color;
}
Car::Color GetColor() const
{
return _color;
}
private:
Car::Color _color;
};
(1) ¿Es esta una buena manera de limitar el alcance de la enumeración de Color
? O, ¿debería declararlo fuera de la clase Car
, pero posiblemente dentro de su propio espacio de nombres o estructura? Acabo de encontrar este artículo hoy, que defiende lo último y analiza algunos aspectos interesantes sobre las enumeraciones: http://gamesfromwithin.com/stupid-c-tricks-2-better-enums .
(2) En este ejemplo, cuando se trabaja dentro de la clase, ¿es mejor codificar la enumeración como Car::Color
o bastará con Color
? (Supongo que el primero es mejor, en caso de que haya otra Enum de Color
declarada en el espacio de nombres global. De esa forma, al menos, somos explícitos sobre la enumeración a la que nos referimos).
En general, siempre pongo mis enums en una struct
. He visto varias pautas que incluyen "prefixing".
enum Color
{
Clr_Red,
Clr_Yellow,
Clr_Blue,
};
Siempre pensé que esto se parecía más a las pautas de C++
que a las de C++
(por ejemplo, debido a la abreviación y también a los espacios de nombres en C++
).
Entonces, para limitar el alcance, ahora tenemos dos alternativas:
- espacios de nombres
- estructuras / clases
Personalmente tiendo a usar una struct
porque puede usarse como parámetros para la programación de plantillas, mientras que un espacio de nombres no puede ser manipulado.
Los ejemplos de manipulación incluyen:
template <class T>
size_t number() { /**/ }
que devuelve la cantidad de elementos de enum dentro de la estructura T
:)
Hoy en día, usando C ++ 11, puedes usar la clase enum para esto:
enum class Color { RED, BLUE, WHITE };
AFAII esto hace exactamente lo que quieres.
Prefiero el siguiente enfoque (código a continuación). Resuelve el problema de "contaminación del espacio de nombres", pero también es mucho más seguro (no puede asignar e incluso comparar dos enumeraciones diferentes, o su enumeración con otros tipos incorporados, etc.).
struct Color
{
enum Type
{
Red, Green, Black
};
Type t_;
Color(Type t) : t_(t) {}
operator Type () const {return t_;}
private:
//prevent automatic conversion for any other built-in types such as bool, int, etc
template<typename T>
operator T () const;
};
Uso:
Color c = Color::Red;
switch(c)
{
case Color::Red:
//некоторый код
break;
}
Color2 c2 = Color2::Green;
c2 = c; //error
c2 = 3; //error
if (c2 == Color::Red ) {} //error
If (c2) {} error
Creé macro para facilitar el uso:
#define DEFINE_SIMPLE_ENUM(EnumName, seq) /
struct EnumName {/
enum type /
{ /
BOOST_PP_SEQ_FOR_EACH_I(DEFINE_SIMPLE_ENUM_VAL, EnumName, seq)/
}; /
type v; /
EnumName(type v) : v(v) {} /
operator type() const {return v;} /
private: /
template<typename T> /
operator T () const;};/
#define DEFINE_SIMPLE_ENUM_VAL(r, data, i, record) /
BOOST_PP_TUPLE_ELEM(2, 0, record) = BOOST_PP_TUPLE_ELEM(2, 1, record),
Uso:
DEFINE_SIMPLE_ENUM(Color,
((Red, 1))
((Green, 3))
)
Algunas referencias útiles:
- Herb Sutter, Jum Hyslop, C / C ++ Users Journal, 22 (5), mayo de 2004
- Herb Sutter, David E. Miller, Bjarne Stroustrup Enumerados fuertemente tipados (revisión 3), julio de 2007
Si está creando una biblioteca de códigos, entonces usaría el espacio de nombres. Sin embargo, solo puede tener una Enumeración de color dentro de ese espacio de nombres. Si necesita una enumeración que podría usar un nombre común, pero podría tener constantes diferentes para diferentes clases, use su enfoque.