Enum बनाम मजबूत टाइप की हुई Enum


84

मैं C ++ प्रोग्रामिंग में एक शुरुआत हूं।

आज मैं एक नए विषय पर आता हूं: दृढ़ता से टाइप किया गया enum। मैंने इस पर थोड़ा शोध किया है लेकिन अब तक मैं यह पता लगाने में असमर्थ हूं कि हमें इसकी आवश्यकता क्यों है और उसी का उपयोग क्या है?

उदाहरण के लिए अगर हमारे पास:

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

हमें लिखने की आवश्यकता क्यों है:

enum class xyz{a, b, c};

हम यहां क्या करने की कोशिश कर रहे हैं? मेरा सबसे महत्वपूर्ण संदेह यह है कि इसका उपयोग कैसे किया जाए। क्या आप एक छोटा सा उदाहरण दे सकते हैं, जो मुझे समझ में आएगा।

जवाबों:


114

ठीक है, पहला उदाहरण: पुरानी शैली के इनमों का अपना दायरा नहीं है:

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!

दूसरा, वे अभिन्न रूप से अभिन्न प्रकारों में बदलते हैं, जिससे अजीब व्यवहार हो सकता है:

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

अंत में, आप अंतर्निहित अभिन्न प्रकार C ++ 11 एनमों को निर्दिष्ट कर सकते हैं:

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

पहले, अंतर्निहित प्रकार निर्दिष्ट नहीं किया गया था, जो प्लेटफार्मों के बीच संगतता समस्याओं का कारण बन सकता है। संपादित करें यह टिप्पणियों में बताया गया है कि आप C ++ 11 में "पुरानी शैली" के अंतर्निहित अभिन्न प्रकार को भी निर्दिष्ट कर सकते हैं।


क्या हमें घोषित / परिभाषित enum class Coloursऔर करने की आवश्यकता है enum class Fruits। क्योंकि जब मैंने VS 2010 में कोड लिखा था। यह एक त्रुटि के "expects a defination or a tag name"तहत आता है class
रस्मी रंजन नायक

इसके अलावा: C ++ 11 में "साधारण"
एनम के लिए

2
इसके अलावा: आप एनुम-एस की घोषणा को आगे कर सकते हैं, यदि निर्दिष्ट अंतर्निहित प्रकार। C ++ 11, C ++ 98 में साधारण एनुम के लिए इसकी अनुमति नहीं है। Microsoft कंपाइलर आपके लिए enum की आगे की घोषणा करने की अनुमति देता है, लेकिन यह केवल MS एक्सटेंशन है, यह standart नहीं है (उदाहरण के लिए gcc इसकी अनुमति नहीं देता है) इसलिए ऐसी कोई चीज़ अब कानूनी है: enum ForwardDeclare: std :: uintor_t;
ब्रजिउज

क्या हम ऐसे शत्रुओं को भी शामिल कर सकते हैं जो निहित रूप से अभिन्न प्रकार में परिवर्तित हो जाते हैं?
एसएस ऐनी

17

इस आईबीएम पृष्ठ पर enums के बारे में एक अच्छा लेख है , यह बहुत विस्तृत और अच्छी तरह से लिखा गया है। यहाँ संक्षेप में कुछ महत्वपूर्ण बिंदु हैं:

स्कूप्ड एनमोंस नियमित एनमों द्वारा की गई अधिकांश सीमाओं को हल करते हैं: पूर्ण प्रकार की सुरक्षा, अच्छी तरह से परिभाषित अंतर्निहित प्रकार, गुंजाइश मुद्दे और आगे की घोषणा।

  • आप अन्य प्रकार के स्कोप किए गए एनम के सभी निहित रूपांतरणों को अस्वीकार करके टाइप सुरक्षा प्राप्त करते हैं।
  • आपको एक नया स्कोप मिलता है, और एनम एनक्लोजिंग स्कोप में नहीं है, खुद को नाम के टकराव से बचा रहा है।
  • स्कोप्ड एनम आपको अंतर्निहित प्रकार के एन्यूमरेशन को निर्दिष्ट करने की क्षमता देता है, और स्कॉप्ड एनम के लिए, यह int को डिफॉल्ट करता है यदि आप इसे निर्दिष्ट नहीं करने के लिए चुनते हैं।
  • एक निश्चित अंतर्निहित प्रकार के साथ किसी भी एनम को आगे घोषित किया जा सकता है।

2
तीसरा और चौथा अंक घिरी हुई गणनाओं के लिए विशिष्ट नहीं है; आप किसी भी गणना के अंतर्निहित प्रकार को निर्दिष्ट कर सकते हैं।
माइक सेमुर

1
किसी के पास पीडीएफ के कम टूटे हुए संस्करण का लिंक है? इसमें कोड उदाहरण मेरे किसी भी पीडीएफ दर्शक को प्रस्तुत नहीं करता है, जो कल्पना के लिए बहुत कुछ छोड़ देता है।
सारा सीनबैक

11

का मान enum classवास्तव में प्रकार का है enum class, underlying_typeसी-एनम के लिए नहीं ।

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);

5

एनम क्लासेस ("नई एनम", "स्ट्रॉन्ग एनम") पारंपरिक सी ++ एन्यूमरेशन्स के साथ तीन समस्याओं का समाधान करती हैं:

  1. पारंपरिक enumsरूप से रूपांतरित होता है int, जिससे त्रुटियां होती हैं जब कोई व्यक्ति पूर्णांक के रूप में कार्य करने के लिए गणना नहीं चाहता है।
  2. पारंपरिक रूप enumsसे आस-पास के दायरे में उनके प्रगणकों को निर्यात किया जाता है, जिससे नाम की हानि होती है।
  3. अंतर्निहित प्रकार को enumनिर्दिष्ट नहीं किया जा सकता है, जिससे भ्रम, संगतता समस्याएं पैदा होती हैं, और आगे की घोषणा को असंभव बना देता है।

enum class ("मजबूत एनम") दृढ़ता से टाइप और स्कोप किए गए हैं:

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

जैसा कि दिखाया गया है, पारंपरिक एनम हमेशा की तरह काम करते हैं, लेकिन अब आप वैकल्पिक रूप से एनम के नाम के साथ अर्हता प्राप्त कर सकते हैं।

नए एनम "एनम क्लास" हैं क्योंकि वे पारंपरिक एनुमरेशंस (नाम मूल्यों) के पहलुओं को वर्गों के पहलुओं (स्कोप्ड सदस्यों और रूपांतरणों की अनुपस्थिति) के साथ जोड़ते हैं।

अंतर्निहित प्रकार को निर्दिष्ट करने में सक्षम होने के लिए सरल अंतर्संचालनीयता और गणना के आकार की गारंटी देता है:

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

यह आगे की घोषणाओं को भी सक्षम बनाता है:

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

अंतर्निहित प्रकार हस्ताक्षरित या अहस्ताक्षरित पूर्णांक प्रकारों में से एक होना चाहिए; डिफ़ॉल्ट है int

मानक पुस्तकालय में, enumकक्षाओं का उपयोग किया जाता है:

  1. मैपिंग सिस्टम विशिष्ट त्रुटि कोड: में <system_error>: enum class errc;
  2. सूचक सुरक्षा संकेतक: में <memory>:enum class pointer_safety { relaxed, preferred, strict };
  3. I / O स्ट्रीम त्रुटियाँ: में <iosfwd>:enum class io_errc { stream = 1 };
  4. अतुल्यकालिक संचार त्रुटि हैंडलिंग: में <future>:enum class future_errc { broken_promise, future_already_retrieved, promise_already_satisfied };

इनमें से कई में ऑपरेटर हैं, जैसे कि ==परिभाषित।


3

एनम स्कोप

Enumerations अपने enumerators को आसपास के दायरे में निर्यात करते हैं। इसकी दो कमियां हैं। सबसे पहले, यह नाम की गड़बड़ी पैदा कर सकता है, अगर एक ही दायरे में घोषित किए गए विभिन्न एनमर्स में दो एनुमरेटर का एक ही नाम हो; दूसरा, पूरी तरह से योग्य नाम के साथ एनुमर नाम का उपयोग करना संभव नहीं है।

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

select = ESet::a; // error
select = a;       // is ambigious
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.