क्यों enum class C++ में आपका नया सबसे अच्छा दोस्त है?
\n\nहर कोई जिसने C++ सीखना शुरू किया या ब्रेक के बाद उस पर लौटा, उसे देर-सबेर एक दुविधा का सामना करना पड़ता है: पुराने अच्छे enum का उपयोग करें या इसके अधिक आधुनिक साथी enum class का? Stack Overflow पर प्रश्न «Why is enum class considered safer to use than plain enum?» ने हजारों व्यूज़ एकत्र किए हैं - और यह आकस्मिक नहीं है। scoped enum (जिसे आधिकारिक तौर पर enum class कहा जाता है) पर स्विच करना सिर्फ फैशन का पालन नहीं है, बल्कि अधिक विश्वसनीय और पठनीय कोड की ओर एक वास्तविक कदम है।
आइए समझते हैं कि पुराने enum में वास्तव में खतरा क्या है और कैसे enum class त्रुटियों के एक पूरे वर्ग से बचने में मदद करता है। यदि आप C++ में लिखते हैं और अभी भी बिना दृश्यता क्षेत्र वाले enum का उपयोग कर रहे हैं - यह लेख आपके लिए है।
पुराने enum की शीर्ष 3 त्रुटियाँ (और enum class उन्हें कैसे ठीक करता है)
\n\n1️⃣ वैश्विक दृश्यता क्षेत्र का प्रदूषण
\n\nपुराने enum की सबसे आम समस्या यह है कि इसके स्थिरांक आसपास के नाम स्थान में "बाहर निकल" जाते हैं। कल्पना करें कि आपके पास दो गणनाएँ हैं:
// बुरा: पुराना enum\nenum Color { Red, Green, Blue };\nenum Feeling { Happy, Sad, Blue }; // संकलन त्रुटि! Blue पहले से परिभाषित है\n\nColor से स्थिरांक Blue पहले से ही लिया गया है, और आप Feeling में उसी नाम का उपयोग नहीं कर सकते। सैकड़ों फ़ाइलों वाले बड़े प्रोजेक्ट में, यह वास्तविक सिरदर्द का कारण बनता है। Color_Blue या COLOR_BLUE जैसे लंबे नाम बनाने पड़ते हैं, जो कोड को बदसूरत बनाता है।
enum class के साथ समाधान:
\n\n// अच्छा: enum class (scoped enum)\nenum class Color { Red, Green, Blue };\nenum class Feeling { Happy, Sad, Blue }; // ठीक है! कोई विरोध नहीं\n\nअब Blue अपनी क्लास के अंदर रहता है। इसे एक्सेस करने के लिए, आपको Color::Blue या Feeling::Blue लिखना होगा। यह न केवल टकराव की समस्या को हल करता है, बल्कि कोड को स्व-दस्तावेजीकरण भी बनाता है - तुरंत दिखता है कि मान किस प्रकार का है।
2️⃣ int में अंतर्निहित रूपांतरण (और वापस)
\n\nपुराना enum अंतर्निहित रूप से पूर्णांक प्रकारों में परिवर्तित हो जाता है। पहली नज़र में यह सुविधाजनक है, लेकिन व्यवहार में यह मुश्किल से पकड़ में आने वाली बगों का स्रोत है।
// खतरनाक पुराना enum\nenum WarningLevel { Low, Medium, High };\n\nvoid setVolume(int level) {\n if (level > 10) level = 10;\n // ...\n}\n\nsetVolume(High); // काम करता है! लेकिन High = 2, वॉल्यूम स्तर नहीं\n// आपने गलती से वॉल्यूम के बजाय अलर्ट स्तर पास कर दिया - कंपाइलर चुप है\n\nकंपाइलर बिना किसी चेतावनी के इसे निगल जाएगा। और यदि आप फ़ंक्शन में तर्कों का क्रम गड़बड़ कर देते हैं - बग रनटाइम में चला जाएगा।
\n\nenum class कैसे सुरक्षा प्रदान करता है:
\n\nenum class WarningLevel { Low, Medium, High };\n\nvoid setVolume(int level);\n\nsetVolume(WarningLevel::High); // संकलन त्रुटि!\n// enum class से int में कोई अंतर्निहित रूपांतरण नहीं\n\nकंपाइलर आपको मान को स्पष्ट रूप से बदलने के लिए मजबूर करेगा, यदि वास्तव में आवश्यक हो। और इसका मतलब है कि आप प्रत्येक रूपांतरण के बारे में जागरूक हैं, न कि "शायद काम कर जाए" पर भरोसा करते हैं।
\n\n// यदि बहुत आवश्यक हो - स्पष्ट रूप से करें\nsetVolume(static_cast<int>(WarningLevel::High)); // स्पष्ट और समझने योग्य\n\n3️⃣ अपरिभाषित आधार प्रकार
\n\nपुराना enum यह गारंटी नहीं देता कि अंदरूनी रूप से किस पूर्णांक प्रकार का उपयोग किया जाएगा। कंपाइलर इसे स्वयं चुनता है (आमतौर पर int), और यह विभिन्न कंपाइलरों या प्लेटफार्मों के बीच स्थानांतरित करते समय अप्रत्याशित स्थितियाँ पैदा कर सकता है।
// आकार भिन्न हो सकता है!\nenum Small { A, B, C }; // int हो सकता है, char हो सकता है\nenum Big { X = 100000, Y, Z }; // फिर भी int हो सकता है\n\nenum class के साथ, आप स्पष्ट रूप से आधार प्रकार निर्दिष्ट कर सकते हैं, जो पूर्ण नियंत्रण देता है