2009-05-22 27 views
31

¿Por qué las personas usan enumeraciones en C++ como constantes cuando pueden usar const?¿Por qué las personas usan enumeraciones en C++ como constantes mientras pueden usar const?

+0

sé que esto es un hilo muy antiguo, pero ¿podrías dar un ejemplo? Cuando leí esta pregunta, estaba pensando en las líneas de código que devuelve un int de una función, pero usa una enumeración para definir 'versiones' específicas del valor de retorno, p. condición de error, tiempo de espera, etc. Algunas de las respuestas a continuación parecen abordar problemas totalmente diferentes a eso. En mi opinión, es incorrecto usar una enumeración de esa manera a menos que, como dicen las personas, tu compilador tenga una funcionalidad limitada wrt estática. – cosimo193

+0

Posible duplicado de [¿Debo usar #define, enum o const?] (Https://stackoverflow.com/questions/112433/should-i-use-define-enum-or-const) –

Respuesta

20

Una enumeración implica un conjunto de relacionadas constantes, por lo que la información adicional sobre la relación debe ser útil en su modelo del problema en cuestión.

+30

Hm, eso no se ve como una respuesta a la pregunta (aunque fue aceptado). Las personas usan enums donde podrían usar 'const' y los valores están ** no ** relacionados. A menudo verá 'enum {ALGO = 2232; } '(como eso; enum sin nombre con un solo valor) en lugar de' const int ALGO = 2232; '.Es porque enum nunca obtiene ningún almacenamiento mientras que la variable const sigue siendo una variable y obtendrá un almacenamiento (estático) si el compilador no puede demostrar que no va a necesitar uno, lo que a menudo no es posible. –

+0

Otra razón es que las variables "const" POD son una característica más reciente de C++, y todavía existen muchas bases de códigos más antiguas (y programadores que prefieren la mayor compatibilidad). –

-1

Una de las razones es que requiere más const escribiendo:

enum { Val1, Val2, Val3 }; 

... ... frente

const int Val1=0, Val2=1, Val3=2; 
+1

No es la única razón. Además, no hay una gran diferencia al escribir. –

34

enumeraciones son tipos distintos, por lo que puede hacer las cosas orientadas de tipo similar a la sobrecarga con ellos:

enum Color { Red,Green,Blue }; 
enum Size { Big,Little }; 

void f(Color c) { 
} 

void f(Size s) { 
} 

int main() { 
    f(Red); 
    f(Big); 
} 
+5

Esto no es lo que hizo la pregunta. La pregunta es: ¿por qué la gente escribe cosas como: enum {Margin = 50}; – Claudio

20

Hay una razón histórica también cuando se trata de una plantilla cumplida programacion Algunos compiladores pueden usar valores de una enumeración, pero no una constante estática int para crear una instancia de una clase.

template <int N> 
struct foo 
{ 
    enum { Value = foo<N-1>::Value + N }; 
}; 

template <> 
struct foo<0> 
{ 
    enum { Value = 0; } 
}; 

Ahora puede hacerlo de la manera más sensata:

template <int N> 
struct foo 
{ 
    static const int Value = foo<N-1>::Value + N; 
}; 

template <> 
struct foo<0> 
{ 
    static const int Value = 0; 
}; 

Otra posible razón es que un const int estática puede tener memoria reservada para ello en tiempo de ejecución, mientras que una enumeración nunca se va a tener una ubicación de memoria real reservada para él, y se repartirá en tiempo de compilación. Ver this related question.

10

Los mensajes son más descriptivos cuando se usan. Considere:

int f(int fg, int bg) 

frente

int f(COLOR fg, COLOR bg) 

Además, las enumeraciones dan un poco más de seguridad de tipos, porque

  • enteros no son implícitamente convertible es posible enumerar los tipos
  • enumeración de uno tipo no es implícitamente convertible en enumeración de otro tipo
+0

Este es un hilo viejo, pero las dos declaraciones al final de esta respuesta son falsas y es necesario corregirlas. – motiz88

+4

"los enteros no son implícitamente convertibles en tipos enum" y "enum de un tipo no es implícitamente convertible a enum de otro tipo" - falso. Normal 'enum's convertirá silenciosamente a/desde enteros, en C++ como en C. Así que estrictamente _no_ proporcionan esta seguridad. Sin embargo, en C++ 11, hay 'enum class' que es un estilo de C++ apropiado" re-imaginando "de' enum': las conversiones implícitas se han ido, y además los nombres de los valores siempre deben ser calificados. Esto es similar a C# 'enum's, y evita los problemas de contaminación de nombre/colisión de nombres que surgen con el antiguo' enum' de C. – motiz88

+0

@ motiz88 - Creo que puede estar confundido en este caso. Pruebe este código en gcc (deberá reformatearlo usted mismo): int main() {enum MyEnum1 {VAL11, VAL12, VAL13}; enum MyEnum2 {VAL21, VAL22, VAL23, VAL24}; int int1 = VAL11; MyEnum1 enum1 = 3; MyEnum2 enum2 = VAL11; enum2 = enum1; int int2 = enum1; return 0; } Los valores Enum se convierten implícitamente en enteros, pero no al revés, y los "tipos enum" no se convierten implícitamente entre sí. En principio, creo que Ask es correcto aquí, pero no creo que sea una respuesta a la pregunta de la operación. – cosimo193

4

enumeraciones también se puede utilizar como un nombre de tipo. De modo que puede definir una función que toma una enumeración como parámetro, lo que deja más claro qué tipos de valores se deben dar como argumentos a la función, en comparación con tener los valores definidos como variables const y la función que acepta simplemente "int" como un argumento

considerar:

enum my_new_fangled_type { 
    baz = 0, 
    meh = 1 
}; 

void foo (my_new_fangled_type bar) // bar can be a value listed in the enum 
{ 
    ... 
} 

frente:

int const baz = 0; 
int const meh = 1; 

void foo (int bar) // what are valid values for bar? 
{ 
    ... 
} 
+1

'typedef int my_new_fangled_type; void foo (my_new_fangled_type bar); 'Problema resuelto, no se necesita ninguna enumeración, y puedo cambiar la representación de la memoria reemplazando' typedef int' con 'typedef uchar' o algo así. :) – weberc2

0

Usando una enumeración documenta las opciones válidas de una manera concisa y permite que el compilador para hacerlas cumplir.

Si están usando las constantes globales de Enum Store, como Pi, por ejemplo, entonces no sé cuál es su objetivo.

+1

enum es un tipo integral, no creo que pueda almacenar una constante como Pi sin pérdida significativa de precisión :) – ASk

+0

pueden almacenar 314159 y simplemente div por 10^5 cada vez: P con suerte el ejemplo da el idea correcta sobre lo que quiero decir con constantes globales, sin embargo. – dss539

10

me gusta el comportamiento automático que puede ser utilizado con enumeraciones, por ejemplo:

enum {NONE, START, HEY, HO, LAST}; 

Entonces es fácil de bucle hasta el pasado, y cuando se añade un nuevo estado (o lo que está representado), el la lógica se adapta

for (int i = NONE; i < LAST; i++) 
{ 
    // Do stuff... 
} 

Añadir algo ...

enum {NONE, START, HEY, WEE, HO, LAST}; 

El bucle se adapta ...

+0

A menos que alguien agregue accidentalmente el nuevo literal enum al final de la lista, o decida dar valores no contiguos a los literales (por ejemplo, enum {} NONE = 0, START = 4, HEY = 7 etc ...). – cosimo193

5

Antes de fabricantes de compiladores implementaron el 14882 ISO/IEC: 1998 estándar C++, este código para definir una constante en un alcance de clase resultó en un error de compilación:

class Foo { 
    static const int MAX_LEN = 80; 
    ... 
}; 

Si la constante es un tipo de entero, un trabajo complejo es d efinir en una enumeración dentro de la clase:

class Foo { 
    enum { 
     MAX_LEN = 80 
    }; 
    ... 
}; 
+0

Las constantes no estáticas no se pueden inicializar de esa manera. Creo que querías decir "static const int Val1". Además, existen inconvenientes en el uso de este método de inicialización en clase: no se garantiza la creación del símbolo de Val1. – ASk

+0

@ASk: El problema es que el símbolo para "static const int Val1" no se garantiza que ** no ** se genere, por lo que el programador usa enum en su lugar, porque eso no crea ningún símbolo en absoluto. –

41

Bruce Eckel da una razón en Thinking in C++:

In older versions of C++, static const was not supported inside classes. This meant that const was useless for constant expressions inside classes. However, people still wanted to do this so a typical solution (usually referred to as the “enum hack”) was to use an untagged enum with no instances. An enumeration must have all its values established at compile time, it’s local to the class, and its values are available for constant expressions. Thus, you will commonly see:

#include <iostream> 
using namespace std; 

class Bunch { 
    enum { size = 1000 }; 
    int i[size]; 
}; 

int main() { 
    cout << "sizeof(Bunch) = " << sizeof(Bunch) 
     << ", sizeof(i[1000]) = " 
     << sizeof(int[1000]) << endl; 
} 

[Editar]

Creo que sería más justo para vincular el sitio de Bruce Eckel : http://www.mindview.net/Books/TICPP/ThinkingInCPP2e.html.

2

Algunos depuradores mostrarán el nombre de la enumeración en lugar de su valor al depurar. Esto puede ser muy útil. Sé que preferiría ver day_of_week = MONDAY que day_of_week = 1.

2

Es en parte porque los compiladores de más edad no apoyaron la declaración de una verdadera constante

class C 
{ 
    const int ARealConstant = 10; 
}; 

clase así que tuvimos que hacer esto

class C 
{ 
    enum { ARealConstant = 10 }; 
}; 

Por esta razón, muchas bibliotecas portátiles seguir utilizando este formulario .

La otra razón es que las enumeraciones se pueden utilizar como un dispositivo sintáctica conveniente de organizar constantes de clase en los que están relacionados, y los que no son

class DirectorySearcher 
{ 
    enum options 
    { 
    showFiles = 0x01, 
    showDirectories = 0x02, 
    showLinks = 0x04, 
    }; 
}; 

vs

class Integer 
{ 
    enum { treatAsNumeric = true }; 
    enum { treatAsIntegral = true }; 
    enum { treatAsString = false }; 
}; 
Cuestiones relacionadas