2009-09-04 10 views
11

La forma típica de definir una constante de utilizar dentro de una función entero es:¿Hay alguna razón para usar enum para definir una sola constante en el código C++?

const int NumbeOfElements = 10; 

la misma para el uso dentro de una clase:

class Class { 
... 
    static const int NumberOfElements = 10; 
}; 

A continuación, se puede utilizar como una matriz de tamaño fijo atado, lo que significa que se conoce en tiempo de compilación.

compiladores Hace mucho tiempo no apoyaron esta última sintaxis y es por eso que se utilizan enumeraciones:

enum NumberOfElementsEnum { NumberOfElements = 10; } 

Ahora, con casi todos los compilador utilizado el apoyo tanto de la en-función const int y la de su clase static const int sintaxis es ¿Hay alguna razón para usar la enumeración para este propósito?

Respuesta

23

La razón es principalmente breve. En primer lugar, un enum puede ser anónima:

class foo { 
    enum { bar = 1 }; 
}; 

Esto introduce efectivamente bar como una constante integral. Tenga en cuenta que lo anterior es más corto que static const int.

Además, nadie podría escribir &bar si es un miembro enum. Si hace esto:

class foo { 
    static const int bar = 1; 
} 

y luego el cliente de la clase hace esto:

printf("%p", &foo::bar); 

entonces se obtendrá un error de vinculador en tiempo de compilación que foo::bar no está definido (porque, bueno, como un lvalue, no lo es). En la práctica, con el estándar tal como se encuentra actualmente, en cualquier lugar se usa bar cuando una expresión constante integral no es requerida (es decirdonde simplemente se permite), requiere una definición fuera de clase de foo::bar. Los lugares donde se requiere dicha expresión son: enum inicializadores, case etiquetas, tamaño de matriz en tipos (excepto new[]) y argumentos de plantilla de tipos integrales. Por lo tanto, usar bar en cualquier otro sitio requiere técnicamente una definición. Consulte C++ Core Language Active Issue 712 para obtener más información: todavía no hay propuestas de resolución.

En la práctica, la mayoría de los compiladores en estos días son más indulgentes con esto y le permiten salirse con la mayoría de los usos de "sentido común" de las variables static const int sin necesidad de una definición. Sin embargo, los casos de las esquinas pueden diferir, sin embargo, muchos consideran que es mejor simplemente usar el enum anónimo, para lo cual todo es muy claro, y no hay ambigüedad en absoluto.

+1

Hmm, gcc no se queja de esto ni siquiera con -peedic -Wall -Wextra. Supongo que porque no puede detectar el error hasta el momento del enlace de todos modos, simplemente se da por vencido al tratar de diagnosticar el código no portátil de este tipo. –

+0

Buena respuesta. Otra cosa agradable que no mencionas explícitamente es que una enumeración es un valor r, y por lo tanto, nunca se le asigna espacio de almacenamiento. Puede ser bueno saber eso * con seguridad *, en lugar de confiar en la optimización del compilador si está haciendo metaprogramación de plantillas y creando una gran cantidad de plantillas de clase. – jalf

+1

Si no hay una definición para 'static const int' fuera de la clase, tampoco se asignará ningún almacenamiento para eso. Además, los valores de valores pueden tener espacio de almacenamiento asignado (por ejemplo, los temporales son valores r, y definitivamente usan almacenamiento). –

-2

línea inferior - use const.

más detalles:

no soy un experto en C++, pero esto parece una pregunta más general de diseño.

Si no es obligatorio, y cree que hay una probabilidad muy baja/inexistente de que la enumeración tenga más de un valor, utilice una const regular. incluso si está equivocado y en algún momento en el futuro habrá más valores, haciendo que una enumeración sea la opción correcta: una refactorización simple y usted cambia a const para enum.

+0

Esto no se trata de 'enum' vs' const' desde el punto de vista del diseño de alto nivel. Todo esto se trata de caprichos de C++ en relación con cada construcción. La respuesta obvia es incorrecta aquí. –

3

Creo que no hay ninguna razón para usar una enumeración, y que en realidad es mejor usar un static const int para este fin, ya que una enumeración tiene su propio tipo (incluso si se puede convertir implícitamente en un entero).

+0

No es que me importe ser votado negativamente, pero sería bueno dejarme saber por qué. Gracias. –

+3

¿Por qué es malo que una enumeración tenga su propio tipo? ¿Su programa tiene una cuota de tipo que no puede exceder? –

+0

Estoy de acuerdo con @Rob Kennedy. La escritura fuerte de constantes es el ** punto ** de enums. –

9

Definición de constantes estáticas directamente en la definición de clase es una adición posterior a C++ y muchos todavía se adhieren a la solución anterior de utilizar un enum para eso. Incluso podría haber algunos compiladores antiguos aún en uso que no admitan constantes estáticas definidas directamente en las definiciones de clases.

+2

Algunos compiladores no siempre alinearán el const int estático, mientras que la enumeración siempre estará AFAIK con línea. –

5

En su caso, usaría una constante también. Sin embargo, hay otros casos en los que I podría agregar otras constantes relacionadas. De esta manera:

const int TextFile = 1; // XXX Maybe add other constants for binary files etc.? 

En tales casos, utilizo una enumeración de inmediato con un solo valor, como este:

enum FileType { 
    TextFile = 1 
    // XXX Maybe add other values for binary files etc.? 
} 

La razón es que el compilador puede emitir advertencias cuando estoy usando el valor constante en las expresiones de conmutación, como en:

FileType type; 
// ... 
switch (type) { 
    case TextFile: 
     // ... 
} 

en caso de que decida añadir otro valor constante que se relaciona con el valor existente (un tipo diferente de archivo, en este ejemplo), prácticamente todos los compiladores Wil Emite una advertencia ya que el nuevo valor no se maneja en la declaración de cambio.

Si hubiera usado 'int' y constantes, el compilador no podría emitir advertencias.

5

La única razón para usar el "enum hack" es que los compiladores antiguos no son compatibles con las definiciones de clase in-class, como dices en tu pregunta.Entonces, a menos que sospeche que su código será portado a un compilador anterior, debe usar const donde const es debido.

1

Bueno, la portabilidad es una buena razón para usar enum. Es genial, porque no tiene que preocuparse si su compilador es compatible con "static const int S = 10" o no ...

Además, por lo que recuerdo, la variable estática debe definirse en alguna parte, así como declarado, y el valor enum debe declararse solo.

+0

No es necesario definir un valor de 'constante estática' de tipo integral si la declaración incluye un inicializador de expresión constante integral, pero las reglas son muy turbias allí. Ver mi respuesta –

5

El uso de enum tiene una ventaja. Un tipo de enumeración es un tipo, por lo que si se define, por ejemplo:

enum EnumType { EnumValue1 = 10, EnumValue2 = 20 ... }; 

y tiene una función como:

void Function1(EnumType Value) 

el compilador comprueba que está pasando un miembro de la EnumType enumeración de la función, por lo que solo los valores válidos para el parámetro Value serían EnumValue1 y EnumValue2. Si utiliza constantes y cambiar la función a

void Function1(int Value) 

el compilador comprueba que está pasando un int (int ninguna, una constante, variable o literal) a la función.

Los tipos de Enum son buenos para agrupar los valores de const relacionados. Por solo un valor constante, no veo ninguna ventaja.

2

Hay una diferencia entre esos dos. Los enums no tienen una dirección hasta donde yo sé. las construcciones estáticas sí, sin embargo. Entonces, si alguien toma la dirección de la const static int, descarta la const, puede modificar el valor (aunque el compilador puede ignorar el cambio porque cree que es const). Esto es por supuesto puro mal y no deberías hacerlo, pero el compilador no puede evitarlo. Esto no puede suceder con enumeraciones.

Y, por supuesto, si (por alguna razón) necesita la dirección de esa const, necesita la constante estática int.

En pocas palabras, enum es un valor de referencia mientras que const static int es un lvalue. Ver http://www.embedded.com/story/OEG20011129S0065 para más detalles.

+0

El cliente no podrá tomar la dirección de una variable de miembro 'static const int' sin una definición. Sin embargo, la distinción Rvalue/lvalue es perfecta. –

+0

El cliente no lo hará, pero cualquiera que mantenga la clase y agregue código más tarde. –

Cuestiones relacionadas