2012-09-25 28 views
49

C++ programlamada yeni başlayan biriyim.Enum vs Çok iyi yazılmış enum

Bugün yeni bir konuyla karşılaşıyorum: enum. Biraz araştırdım ama şu ana kadar neden buna ihtiyacımız olduğunu ve bunun nasıl kullanıldığını anlayamıyorum? Örneğin

biz varsa:

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

Neden yazmak gerekiyor:

Burada yapmaya çalıştığımız şey
enum class xyz{a, b, c}; 

? En önemli şüphe onu nasıl kullanacağım. Bana anlam verebilecek küçük bir örnek verebilir misiniz? enum class ait

+0

[wikipedia] 'ya bakabilirsiniz (http://en.wikipedia.org/wiki/C%2B%2B11#Strongly_typed_enumerations)? – Nobody

+1

@Nobody: Evet, wiki'ye baktım ama nasıl kullanılacağını anlayamadım ve ne faydaları var. –

cevap

72

Tamam, ilk örnek:

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! 

İkincisi, örtük tamsayı türlere dönüştürmek, garip davranışlara yol açabilir:

bool b = Bear && Duck; // what? 
eski tarz Çeteleler kendi kapsamını yok

Son olarak, C++ 11 enumlarının temel tümleşik türünü belirtebilirsiniz:

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

Önceden, platformlar arasında uyumluluk sorunlarına neden olabilecek temel tür belirtilmemiş. Edit Ayrıca, C++ 11'deki "eski stil" enumun temel tümleyici türünü de belirtebileceğiniz yorumlarda belirtilmiştir.

+0

"Enum class Colours" ve "enum class Fruits" öğelerini bildirmemiz/tanımlamamız gerekiyor. Çünkü bu kodu VS 2010'da yazdığımda. Bir hata atar "," sınıfının altında bir tanım ya da etiket adı bekler. –

+0

Haklı olabilirsiniz. Ben de aynısını kontrol edeceğim. –

+0

Ayrıca: C++ 11'deki C++ 11'deki "sıradan" enum için varsayılan temel türü tanımlı değil – bruziuz

7

Değerler gerçekten tip enum class C-çeteleler gelince değil underlying_type taşımaktadır.

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

this IBM page numarasından enumlar hakkında iyi bir makale var, çok detaylı ve iyi yazılmış. Özetle bazı önemli noktalar şunlardır:

Kapsamlı enumlar, düzenli enumların neden olduğu sınırlamaların çoğunu çözer: tam tip güvenliği, iyi tanımlanmış temel tür, kapsam sorunları ve ileri bildirim.

  • Kapsamlı enumların tüm örtülü dönüşümlerini diğer türlere vermeyerek, tür güvenliğine sahip olursunuz.
  • Yeni bir kapsam elde edersiniz ve enum, kendini kapsam içinde, ad çakışmasından kurtarır.
  • Kapsamlı enumlar, sayımın altta yatan türünü ve kapsamlı enumları belirtme olanağını verir; bunu belirtmemeyi seçerseniz varsayılan olarak int olur.
  • Sabit bir altta yatan türdeki herhangi bir numara ileriye bildirilebilir.
+1

Üçüncü ve dördüncü noktalar kapsamlandırılmış numaralandırmalara özel değildir; Herhangi bir sayımın temelini belirtebilirsiniz. –

3

Enum Kapsam

Numaralandırmalar çevreleyen kapsamına onların enumerator'ler ihracat. Bunun iki dezavantajı var. Birincisi, aynı kapsamda bildirilen farklı enumlarda iki sayım memurunun aynı isme sahip olması durumunda isim çatışmalarına yol açabilir; ikinci olarak, enumerator dahil olmak üzere tam nitelikli bir adla bir numaralandırıcı kullanmak mümkün değildir.

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

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

enum sınıfları ("Yeni çeteleler", "güçlü çeteleler") geleneksel C++ numaralandırma ile üç sorunları çözmek: Birisi, bir istemiyor hatalara neden örtülü int dönüştürmek

  1. konvansiyonel enums bir tamsayı olarak hareket etmek için numaralandırma. konvansiyonel enums numaralarını dışa aktararak, ad çakışmasına neden olur.
  2. enum'un temel türü belirtilemez, bu da karışıklığa, uyumluluk sorunlarına neden olur ve bildirimi imkansız hale getirir.

enum class ("güçlü çeteleler") kesinlikle yazılı ve kapsamına eklenir: gösterildiği gibi

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 

, geleneksel çeteleler her zamanki gibi çalışır, ancak artık isteğe ENUM adı ile hak kazanabilirler.

Yeni enumlar "enum sınıfı" dır çünkü geleneksel sayımların (ad değerleri) yönlerini sınıfların yönleriyle (kapsam üyeleri ve dönüşümlerin olmaması) birleştirirler. çeteleler

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 

Ayrıca sağlayan ileri beyanı:

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 

yatan tip biri olmalıdır yatan türünü belirtmek için güçlü olmak

numaralandırma basit çalışabilirliği ve garantili boyutlarına izin veren imzalı veya imzasız tamsayı türleri; Varsayılan int'dur.

  1. Eşleme sistemleri özel hata kodları: Standart kütüphanesinde

    , enum sınıfları için kullanılan <system_error> olarak: enum class errc;
  2. İşaretçi güvenlik göstergeleri: <memory> olarak: enum class pointer_safety { relaxed, preferred, strict };
  3. I/O akışı hataları: <iosfwd> olarak: enum class io_errc { stream = 1 };
  4. Asenkron iletişim hata işleme: <future> olarak: Bunlardan enum class future_errc { broken_promise, future_already_retrieved, promise_already_satisfied };

Çeşitli olan operatörler, örneğin == tanımlandı.

+0

http://www.stroustrup.com/C++11FAQ.html adresinden alıntılandı – deceze