2012-09-25 20 views
49

Sono un principiante nella programmazione C++.Enum contro enum fortemente tipizzato

Oggi mi imbatto in un nuovo argomento: fortemente digitato enum. Ho studiato un po 'ma fino ad ora non riesco a scoprire perché ne abbiamo bisogno e a che cosa serve lo stesso?

Per esempio, se si ha:

enum xyz{a, b, c}; 
/*a = 0, b = 1, c = 2, (Typical C format)*/ 

Perché abbiamo bisogno di scrivere:

enum class xyz{a, b, c}; 

Cosa stiamo cercando di fare qui? Il mio dubbio più importante è come usarlo. Potresti fornire un piccolo esempio, che mi farà capire.

+0

Hai dato un'occhiata a [wikipedia] (http://en.wikipedia.org/wiki/C%2B%2B11#Strongly_typed_enumerations)? – Nobody

+1

@Nobody: Sì, ho visto 'wiki', ma non sono riuscito a capire come usarlo e quali sono i vantaggi. –

risposta

72

OK, primo esempio: enumerazioni vecchio stile non hanno un proprio campo di applicazione:

enum Animals {Bear, Cat, Chicken}; 
enum Birds {Eagle, Duck, Chicken}; // error! Chicken has already been declared! 

enum class Fruits { Apple, Pear, Orange }; 
enum class Colours { Blue, White, Orange }; // no problem! 

In secondo luogo, essi implicitamente convertire in tipi integrali, che può portare a comportamenti strani:

bool b = Bear && Duck; // what? 

Infine, è possibile specificare il tipo integrale sottostante di enumerazioni C++ 11:

enum class Foo : char { A, B, C}; 

In precedenza, il tipo sottostante non è stato specificato, il che potrebbe causare problemi di compatibilità tra piattaforme. Modifica È stato sottolineato nei commenti che è possibile specificare anche il tipo integrale sottostante di un enum "vecchio stile" in C++ 11.

+0

Abbiamo bisogno di dichiarare/definire 'enum class Colours' e' enum class Fruits'. Perché quando ho scritto il codice in VS 2010. Getta un errore "" si aspetta una definizione o un nome di tag "' sotto 'class'. –

+0

Forse hai ragione. Controllerò lo stesso –

+0

Inoltre: per l'enumerazione "ordinaria" in C++ 11 come in C++ 98 il tipo sottostante predefinito non è definito – bruziuz

7

I valori di enum class sono in realtà di tipo enum class, non underlying_type come per C-enums.

enum xyz { a, b, c}; 
enum class xyz_c { d, f, e }; 

void f(xyz x) 
{ 
} 

void f_c(xyz_c x) 
{ 
} 

// OK. 
f(0); 
// OK for C++03 and C++11. 
f(a); 
// OK with C++11. 
f(xyz::a); 
// ERROR. 
f_c(0); 
// OK. 
f_c(xyz_c::d); 
13

C'è un buon articolo sull'enumerazione allo this IBM page, è molto dettagliato e ben scritto. Ecco alcuni punti importanti in breve:

Le enunciate dell'ambito risolvono la maggior parte dei limiti incontrati dalle normali enumerazioni: completa sicurezza del tipo, tipo sottostante ben definito, problemi di ambito e dichiarazione anticipata.

  • È possibile ottenere la sicurezza del tipo escludendo tutte le conversioni implicite di enumerazione dell'ambito in altri tipi.
  • Si ottiene un nuovo ambito e l'enumerazione non è più nell'intervallo di chiusura, salvandosi dai conflitti di nome.
  • Le enumerazioni scopate consentono di specificare il tipo sottostante dell'enumerazione e, per le enumerazioni dell'ambito, assume come valore predefinito int se si sceglie di non specificarlo.
  • Qualsiasi enum con un tipo sottostante fisso può essere inoltrato dichiarato.
+1

Il terzo e il quarto punto non sono specifici per le enumerazioni con ambito; puoi specificare il tipo sottostante di qualsiasi enumerazione. –

3

Enum Ambito

enumerazioni esportare i propri enumeratori per l'ambito circostante. Questo ha due inconvenienti. In primo luogo, può portare a conflitti di nomi, se due enumeratori in enumerazioni diverse dichiarate nello stesso ambito hanno lo stesso nome; in secondo luogo, non è possibile utilizzare un enumeratore con un nome completo, incluso il nome enum.

enum ESet {a0, a, a1, b1, c3}; 
enum EAlpha{a, b, c} 

select = ESet::a; // error 
select = a;  // is ambigious 
2

Le classi enum ("nuovi enumerazioni", "enums forti") affrontano tre problemi con le enumerazioni tradizionali C++:

  1. convenzionale enums convertire implicitamente a int, causando errori quando qualcuno non vuole un enumerazione di agire come un intero.
  2. convenzionale enums esportare i relativi enumeratori nell'ambiente circostante, causando conflitti di nomi.
  3. Il tipo sottostante di enum non può essere specificato, causando confusione, problemi di compatibilità e rende impossibile la dichiarazione diretta.

enum class ("enumerazioni forti") sono fortemente tipizzati e scope:

enum Alert { green, yellow, orange, red }; // traditional enum 

enum class Color { red, blue }; // scoped and strongly typed enum 
            // no export of enumerator names into enclosing scope 
            // no implicit conversion to int 
enum class TrafficLight { red, yellow, green }; 

Alert a = 7;    // error (as ever in C++) 
Color c = 7;    // error: no int->Color conversion 

int a2 = red;    // ok: Alert->int conversion 
int a3 = Alert::red;  // error in C++98; ok in C++11 
int a4 = blue;   // error: blue not in scope 
int a5 = Color::blue;  // error: not Color->int conversion 

Color a6 = Color::blue; // ok 

Come mostrato, enumerazioni tradizionali funzionano come al solito, ma ora è possibile opzionalmente qualificare con il nome del enum.

Le nuove enumerazioni sono "enumerate" perché combinano aspetti delle enumerazioni tradizionali (valori dei nomi) con aspetti delle classi (membri dell'ambito e assenza di conversioni).

Essere in grado di specificare il tipo di fondo permettono più semplice l'interoperabilità e le dimensioni garantiti di enumerazioni:

enum class Color : char { red, blue }; // compact representation 

enum class TrafficLight { red, yellow, green }; // by default, the underlying type is int 

enum E { E1 = 1, E2 = 2, Ebig = 0xFFFFFFF0U }; // how big is an E? 
               // (whatever the old rules say; 
               // i.e. "implementation defined") 

enum EE : unsigned long { EE1 = 1, EE2 = 2, EEbig = 0xFFFFFFF0U }; // now we can be specific 

Consente inoltre dichiarazione anticipata di enumerazioni:

enum class Color_code : char;  // (forward) declaration 
void foobar(Color_code* p);  // use of forward declaration 
// ... 
enum class Color_code : char { red, yellow, green, blue }; // definition 

Il tipo di fondo deve essere uno dei tipi di interi con segno o senza segno; il valore predefinito è int.

nella libreria standard, enum classi sono utilizzate per: specifici codici di errore

  1. sistemi di mappatura: In <system_error>: enum class errc;
  2. indicatori di sicurezza
  3. Pointer: In <memory>: enum class pointer_safety { relaxed, preferred, strict };
  4. errori I/O stream: In <iosfwd>: enum class io_errc { stream = 1 };
  5. comunicazioni asincrone di gestione degli errori: In <future>: enum class future_errc { broken_promise, future_already_retrieved, promise_already_satisfied };

Molti di questi sono operatori, come ad esempio == definito.

+0

plagiato da http://www.stroustrup.com/C++11FAQ.html – deceze