2012-03-09 12 views
13

¿Debería declarar enumeraciones dentro o fuera de una clase si dichas enumeraciones solo se usan en las funciones de miembros de la clase?¿Deberías declarar enumeraciones dentro o fuera de una clase?

namespace nspace 
{ 

// need to append OC, as this pollutes the current namespace 
enum OUTSIDE_CLASS {OC_POINTS, OC_LINES, OC_LINE_LOOP, :::}; 
enum OTHER_ENUM {OE_POINTS}; 
class VertexBuffer 
{ 
public: 
    enum INSIDE_CLASS {POINTS, LINES, LINE_LOOP, :::}; 
    void foo(OUTSIDE_CLASS e); 
    void bar(INSIDE_CLASS e); 
} 
}; 

// usage 
nspace::VertexBuffer v; 
v.foo(nspae::VB_POINTS); 
v.bar(nspace::VertexBuffer::POINTS); // more pedantic 
+7

Al igual que con todas las preguntas [de estilo de codificación], la respuesta es "depende". –

+2

Alguien podría tener un poco más de conocimiento sobre esto que yo, pero mi estrategia siempre ha sido no exponer algo hasta que deba ser expuesto. (En otras palabras, si solo se usa internamente, guárdela interna.) – Corbin

+0

Como es habitual con las preguntas sobre el estilo de codificación, no hay una respuesta definitiva.Contaminar el alcance global generalmente no es una buena idea debido al riesgo de declaraciones conflictivas, pero si se está dentro de su "propio" espacio de nombres, es estrictamente una cuestión de preferencia. –

Respuesta

14

El objetivo real es evitar contaminar el ámbito (ya sea global o de nombre) y ayudar a agrupar los valores relacionados (funciona bastante bien con autocompletado en IDE).

con C++ 11, se puede declarar inflexible enumeraciones usando:

enum class MyEnum { 
    Value0, 
    Value1 
}; 

que son necesariamente invocada como MyEnum::Value0 (y no Value0).

en C++ 03, puede más o menos emular esto con:

struct MyEnum { 
    enum Type { 
    Value0, 
    Value1 
    }; 
}; 

Pero entonces el tipo de la enumeración es MyEnum::Type que es sutilmente diferente.

La opción perezoso es simplemente lo descarga en una clase, pero todavía favorece la anidación de una enumeración restringidos, incluso dentro de una clase, sólo para que quede claro que esos valores no son suelta sino que están relacionados entre sí .

+1

-1 "Esto evita contaminar el alcance global". No, no, pero si esa declaración tiene que estar en el ámbito global (que rara vez tiene que hacerlo), la contaminación se reduce a un solo nombre (el nombre del tipo) en lugar de a múltiples nombres (los valores enum). –

+1

@ Cheersandhth.-Alf: Correcto, restos de mi tren de ideas, la verdadera intención se expresó en la introducción * evitar contaminar el alcance (ya sea global o de nombre) *. Yo recomendaría siempre el uso de espacios de nombres ... espero que las secuencias de comandos como los programas (en C++, sí!) Rara vez lo requieren. –

+1

ok, eliminado Votación –

8

Si tan sólo los miembros de su clase de uso de la enum es preferible declarar la enum dentro de la clase.
Esto evita que el espacio de nombres/espacio global de la contaminación debida a los nombres de símbolos que no sean necesarios & también
es más intutive para los usuarios de la clase, que ayuda al usuario a saber que el enum solamente será utilizada por la clase.

La regla general es que debe seguir:
No agregue cualquier símbolo en un ámbito (espacio de nombres global /) que no se vaya a acceder (& por lo tanto, no es necesario) en ese ámbito.

+0

-1 el espacio de nombres global no es la única alternativa a la declaración en clase. –

+0

@ Cheersandhth.-Alf: La respuesta no dice que el espacio de nombres global es una alternativa a la declaración en clase, solo dice por qué no es una buena idea en este caso. Estoy un poco confundido con respecto a lo que están bajando votos aquí. –

+0

"Esto evita que el espacio global se contamine" no tendría sentido sin la suposición de que el espacio de nombres global es la única alternativa. –

0

Como mencionó Matthieu M., en C++ 11 usa Strongly typed enumerations.

Una buena manera de emularlos en C++ 03 es envolver enumeraciones en espacios de nombres. Es mejor que envolver en un struct porque ese espacio de nombre puede tener funciones que se pueden encontrar utilizando la búsqueda de nombres dependiente del argumento. Por ejemplo:

namespace MyEnum { 
    enum Type { 
    Value0, 
    Value1 
    }; 

    std::ostream& operator<<(std::ostream&, Type); 
    std::istream& operator>>(std::istream&, Type&); 
} 

MyEnum::Type value; 
std::cout << value; // uses the overload from MyEnum 
std::cin >> value; // uses the overload from MyEnum 
+0

-1 "es mejor porque" debería ser "Prefiero porque". Por ejemplo, prefiero envolverse en estructuras porque las estructuras pueden ser definidas por tipos dentro de las clases (no se puede tener "usar el espacio de nombres" dentro de una clase). La forma en que escribí eso ahora está bien, pero si declaro que mi preferencia es "mejor" que la preferencia de otra persona, entonces sería una afirmación sin sentido o simplemente incorrecta. –

+0

Como dijo Alf, prefiero usar structs para la habilidad 'typedef'. Colocar las funciones en el espacio de nombres en el que reside la estructura que contiene la enumeración es suficiente para que ADL lo active. –

+0

@Alf: 'typedef' y' using namespace' hacen cosas diferentes, por lo que no está claro por qué las comparaste, te puede gustar elaborar. Escribí "mejor" y expliqué cómo. –

0

Depende. Esfuércese por minimizar la exposición de los detalles de implementación. P.ej. adjuntar cosas en espacios de nombres y/o clases y/o archivos de implementación compilados por separado. Y como es de esperar que lo deje muy en claro, el espacio de nombres global y en clase no son las únicas opciones. Es decir, declarar algo en clase no es la única manera de minimizar la exposición (¿qué otras formas hay entonces? --- oh, bueno, recuerda la tercera oración de esta respuesta).

Cuestiones relacionadas