[C++] सादा enum पर enum वर्ग क्यों पसंद किया जाता है?


Answers

बजेर्न स्ट्राउस्ट्रप के सी ++ 11 एफएक्यू से :

enum class es ("new enums", "strong enums") पारंपरिक सी ++ गणनाओं के साथ तीन समस्याओं को संबोधित करते हैं:

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

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

इसलिए, जैसा कि अन्य उपयोगकर्ताओं द्वारा उल्लिखित है, "मजबूत enums" कोड को सुरक्षित बनाएगा।

एक "क्लासिक" enum का अंतर्निहित प्रकार enum सभी मूल्यों को फिट करने के लिए पर्याप्त एक पूर्णांक प्रकार होगा; यह आमतौर पर एक int । इसके अलावा प्रत्येक समेकित प्रकार char या हस्ताक्षरित / हस्ताक्षरित पूर्णांक प्रकार के साथ संगत होगा।

यह एक विस्तृत वर्णन है कि एक enum अंतर्निहित प्रकार होना चाहिए, इसलिए प्रत्येक कंपाइलर क्लासिक enum के अंतर्निहित प्रकार के बारे में अपने आप पर निर्णय लेगा और कभी-कभी परिणाम आश्चर्यजनक हो सकता है।

उदाहरण के लिए, मैंने इस तरह के कोड को कई बार देखा है:

enum E_MY_FAVOURITE_FRUITS
{
    E_APPLE      = 0x01,
    E_WATERMELON = 0x02,
    E_COCONUT    = 0x04,
    E_STRAWBERRY = 0x08,
    E_CHERRY     = 0x10,
    E_PINEAPPLE  = 0x20,
    E_BANANA     = 0x40,
    E_MANGO      = 0x80,
    E_MY_FAVOURITE_FRUITS_FORCE8 = 0xFF // 'Force' 8bits, how can you tell?
};

उपर्युक्त कोड में, कुछ E_MY_FAVOURITE_FRUITS कोडर सोच रहा है कि कंपाइलर E_MY_FAVOURITE_FRUITS मानों को एक हस्ताक्षरित 8 बिट प्रकार में संग्रहीत करेगा ... लेकिन इसके बारे में कोई वारंटी नहीं है: संकलक unsigned char या int या short चुन सकता है, इनमें से कोई भी प्रकार बड़ा है enum में देखा सभी मूल्य फिट करने के लिए पर्याप्त है। फ़ील्ड जोड़ना E_MY_FAVOURITE_FRUITS_FORCE8 एक बोझ है और यह कंपाइलर को अंतर्निहित प्रकार के बारे में किसी भी प्रकार की पसंद करने के लिए मजबूर नहीं करता है।

यदि कोड का कुछ टुकड़ा है जो प्रकार के आकार पर निर्भर करता है और / या मानता है कि E_MY_FAVOURITE_FRUITS कुछ चौड़ाई (उदाहरण: क्रमबद्धता दिनचर्या) का होगा तो यह कोड संकलक विचारों के आधार पर कुछ अजीब तरीकों से व्यवहार कर सकता है।

और मामलों को और भी खराब बनाने के लिए, अगर कुछ कार्यकर्ता लापरवाही से हमारे enum लिए एक नया मूल्य जोड़ता है:

    E_DEVIL_FRUIT  = 0x100, // New fruit, with value greater than 8bits

कंपाइलर इसके बारे में शिकायत नहीं करता है! यह सिर्फ enum सभी मूल्यों को फिट करने के लिए प्रकार का आकार बदलता है (यह मानते हुए कि संकलक सबसे छोटे प्रकार का उपयोग कर रहे थे, जो एक धारणा है जिसे हम नहीं कर सकते हैं)। enum लिए यह सरल और लापरवाह जोड़ा subtlety ब्रेक संबंधित कोड सकता है।

चूंकि सी ++ 11 enum और enum class (धन्यवाद rdb ) के अंतर्निहित प्रकार को निर्दिष्ट करना संभव है, इसलिए इस समस्या को अच्छी तरह से संबोधित किया गया है:

enum class E_MY_FAVOURITE_FRUITS : unsigned char
{
    E_APPLE        = 0x01,
    E_WATERMELON   = 0x02,
    E_COCONUT      = 0x04,
    E_STRAWBERRY   = 0x08,
    E_CHERRY       = 0x10,
    E_PINEAPPLE    = 0x20,
    E_BANANA       = 0x40,
    E_MANGO        = 0x80,
    E_DEVIL_FRUIT  = 0x100, // Warning!: constant value truncated
};

अंतर्निहित प्रकार निर्दिष्ट करना यदि किसी फ़ील्ड में इस प्रकार की सीमा से अभिव्यक्ति है तो संकलक अंतर्निहित प्रकार को बदलने के बजाय शिकायत करेगा।

मुझे लगता है कि यह एक अच्छा सुरक्षा सुधार है।

तो enum वर्ग सादा enum पर पसंद क्यों है? , अगर हम स्कॉप्ड ( enum class ) और unscoped ( enum ) enums के लिए अंतर्निहित प्रकार चुन सकते हैं तो एनम enum class को बेहतर विकल्प कौन बनाता है ?:

  • वे अंतर्निहित रूप से int परिवर्तित नहीं करते हैं।
  • वे आस-पास के नामस्थान को प्रदूषित नहीं करते हैं।
  • उन्हें आगे घोषित किया जा सकता है।
Question

मैंने कुछ लोगों को उनकी प्रकार की सुरक्षा के कारण सी ++ में एनम कक्षाओं का उपयोग करने की सिफारिश की।

लेकिन असल में उसका क्या अर्थ है?




पूर्णांक मानों के सेट का प्रतिनिधित्व करने के लिए गणना का उपयोग किया जाता है।

enum बाद class कीवर्ड निर्दिष्ट करता है कि गणना दृढ़ता से टाइप की जाती है और इसके गणक स्कॉप्ड होते हैं। इस तरह enum वर्ग स्थिरांक के आकस्मिक दुरुपयोग से बचाता है।

उदाहरण के लिए:

enum class Animal{Dog, Cat, Tiger};
enum class Pets{Dog, Parrot};

यहां हम पशु और पालतू जानवरों के मूल्यों को मिश्रण नहीं कर सकते हैं।

Animal a = Dog;       // Error: which DOG?    
Animal a = Pets::Dog  // Pets::Dog is not an Animal