2009-09-04 25 views
11

एक पूर्णांक एक समारोह के अंदर उपयोग करने के लिए निरंतर परिभाषित करने के लिए विशिष्ट तरीका है:क्या सी ++ कोड में एकल स्थिरता को परिभाषित करने के लिए enum का उपयोग करने का कोई कारण है?

const int NumbeOfElements = 10; 

एक वर्ग के भीतर का उपयोग कर के लिए एक ही:

class Class { 
... 
    static const int NumberOfElements = 10; 
}; 

यह तो एक निश्चित-आकार सरणी के रूप में इस्तेमाल किया जा सकता बाध्य जिसका मतलब है कि यह संकलन समय पर जाना जाता है।

बहुत वर्ष पहले compilers बाद वाक्य रचना का समर्थन नहीं किया और यही कारण है enums इस्तेमाल किया गया है:

enum NumberOfElementsEnum { NumberOfElements = 10; } 

अब लगभग हर व्यापक रूप से इस्तेमाल संकलक समर्थन के साथ दोनों में समारोह const int और इन-क्लास static const int वाक्य रचना है इस उद्देश्य के लिए enum का उपयोग करने का कोई कारण है?

उत्तर

23

कारण मुख्य रूप से संक्षिप्त है। सबसे पहले, एक enum गुमनाम हो सकते हैं:

class foo { 
    enum { bar = 1 }; 
}; 

यह प्रभावी रूप से एक अभिन्न निरंतर रूप bar परिचय देता है। ध्यान दें कि उपर्युक्त static const int से छोटा है।

इसके अलावा, कोई भी &bar लिख सकता है यदि यह enum सदस्य है। आप ऐसा करते हैं:

class foo { 
    static const int bar = 1; 
} 

और फिर अपने वर्ग के ग्राहक इस करता है:

printf("%p", &foo::bar); 

तो वह एक संकलन समय लिंकर त्रुटि है कि foo::bar परिभाषित नहीं है मिल जाएगा (क्योंकि, ठीक है, के रूप में एक लालसा, यह नहीं है)। व्यावहारिक रूप से, मानक के साथ वर्तमान में खड़ा है, कहीं भी bar का उपयोग किया जाता है जहां एक अभिन्न निरंतर अभिव्यक्ति आवश्यक (यानी।जहां इसे केवल अनुमति है), इसे foo::bar. की आउट-ऑफ-क्लास परिभाषा की आवश्यकता होती है, जहां ऐसी अभिव्यक्ति की आवश्यकता होती है: enum प्रारंभकर्ता, case लेबल, सरणी आकार (new[] को छोड़कर), और अभिन्न प्रकार के टेम्पलेट तर्क। इस प्रकार, bar का उपयोग करके कहीं और तकनीकी रूप से एक परिभाषा की आवश्यकता होती है। अधिक जानकारी के लिए C++ Core Language Active Issue 712 देखें - अभी तक कोई प्रस्तावित प्रस्ताव नहीं है।

प्रैक्टिस में, इन दिनों अधिकांश कंपाइलर इस बारे में अधिक उदार हैं, और आपको परिभाषा की आवश्यकता के बिना static const int चर के अधिकांश "सामान्य ज्ञान" उपयोगों से दूर जाने देंगे। हालांकि, कोने के मामले अलग-अलग हो सकते हैं, हालांकि, बहुत से लोग अज्ञात enum का उपयोग करने के लिए बेहतर मानते हैं, जिसके लिए सब कुछ क्रिस्टल स्पष्ट है, और बिल्कुल कोई अस्पष्टता नहीं है।

+1

हम्म, जीसीसी इस बारे में शिकायत नहीं करता है -पैंटिक -Wall -Wextra के साथ भी। मुझे लगता है क्योंकि यह लिंक समय तक त्रुटि का पता नहीं लगा सकता है, यह इस तरह के गैर पोर्टेबल कोड का निदान करने की कोशिश करने पर छोड़ देता है। –

+0

अच्छा जवाब। एक और अच्छी बात यह है कि आप स्पष्ट रूप से उल्लेख नहीं करते हैं कि एक enum एक रैल्यू है, और इसलिए इसके लिए कोई भंडारण आवंटित नहीं किया जाता है। यह जानना अच्छा लगेगा कि * निश्चित रूप से *, यदि आप टेम्पलेट मेटाप्रोग्रामिंग कर रहे हैं और बड़ी संख्या में क्लास टेम्पलेट्स को तत्काल कर रहे हैं तो संकलक अनुकूलन पर भरोसा करने के बजाय। – jalf

+1

यदि वर्ग के बाहर 'स्थिर कॉन्स int' के लिए कोई परिभाषा नहीं है, तो उसके लिए आवंटित कोई भी संग्रहण नहीं होगा। इसके अलावा, रावलों के पास उनके लिए आवंटित भंडारण भी हो सकता है (उदाहरण के लिए, अस्थायी हैं, और वे निश्चित रूप से भंडारण का उपयोग करते हैं)। –

-2

नीचे पंक्ति - उपयोग कॉन्स।

अधिक जानकारी के:

मैं एक C++ विशेषज्ञ नहीं हूँ, लेकिन यह एक अधिक सामान्य डिजाइन सवाल लगता है।

यदि यह जरूरी नहीं है, और आपको लगता है कि बहुत कम/अस्तित्वहीन संभावना है कि enum एक मूल्य के बाद बढ़ेगा, फिर नियमित आधार का उपयोग करें। भले ही आप गलत हैं और भविष्य में किसी बिंदु पर और अधिक मूल्य होंगे, जिससे एक सही विकल्प बन जाए - एक साधारण रिफैक्टरिंग और आप इसे enum में बदल दें।

+0

यह उच्च स्तर के डिज़ाइन बिंदु दृश्य से 'enum' बनाम 'const' के बारे में नहीं है। यह प्रत्येक निर्माण के संबंध में सी ++ quirks के बारे में सब कुछ है। स्पष्ट जवाब यहां गलत है। –

3

मुझे लगता है कि इस उद्देश्य के लिए static const int का उपयोग करना वास्तव में बेहतर है, क्योंकि एक enum का अपना प्रकार होता है (भले ही पूर्णांक में पूर्ण रूप से परिवर्तनीय हो)।

+0

ऐसा नहीं है कि मुझे कमजोर होना चाहिए, लेकिन मुझे यह बताना अच्छा लगेगा कि क्यों। धन्यवाद। –

+3

यह क्यों बुरा है कि एक enum का अपना प्रकार है? क्या आपके प्रोग्राम में एक प्रकार का कोटा है जिसे आपको पार करने की अनुमति नहीं है? –

+0

@ रोब केनेडी से सहमत। स्थिरांक का मजबूत टाइपिंग enums के ** बिंदु ** है। –

9

कक्षा परिभाषा में सीधे स्थिर स्थिरांक को परिभाषित करना सी ++ के बाद का जोड़ा है और इसके लिए कई लोग enum का उपयोग करने के पुराने कामकाज से चिपके रहते हैं। यहां तक ​​कि कुछ पुराने कंपाइलर भी उपयोग में हो सकते हैं जो क्लास परिभाषाओं में सीधे परिभाषित स्थिर स्थिरांक का समर्थन नहीं करते हैं।

+2

कुछ कंपाइलर हमेशा स्थिर कॉन्स int को रेखांकित नहीं करेंगे, जबकि enum हमेशा AFAIK रेखांकित किया जाएगा। –

5

आपके मामले में, मैं स्थिर भी उपयोग करता हूं। हालांकि, ऐसे अन्य मामले हैं जहां मैं अन्य, संबंधित स्थिरांक जोड़ सकता हूं। इस तरह:

const int TextFile = 1; // XXX Maybe add other constants for binary files etc.? 

ऐसे मामलों में, मैं एक enum अभी किसी एकल मान के साथ इस तरह का उपयोग करें,:

enum FileType { 
    TextFile = 1 
    // XXX Maybe add other values for binary files etc.? 
} 

कारण है कि संकलक तो चेतावनी जारी कर सकते हैं जब मैं उपयोग कर रहा हूँ स्विच भाव में निरंतर मूल्य, के रूप में:

FileType type; 
// ... 
switch (type) { 
    case TextFile: 
     // ... 
} 

मामले मैं एक निरंतर मूल्य जो मौजूदा मूल्य से संबंधित है (फ़ाइल का एक अलग प्रकार, इस उदाहरण में) जोड़ने का निर्णय में, लगभग सभी compilers Wil मैं एक चेतावनी जारी करता हूं क्योंकि स्विच स्टेटमेंट में नए मान को नियंत्रित नहीं किया जाता है।

यदि मैंने इसके बजाय 'int' और स्थिरांक का उपयोग किया था, तो संकलक को चेतावनियां जारी करने का मौका नहीं होगा।

5

"एनम हैक" का उपयोग करने का एकमात्र कारण यह है कि पुराने कंपाइलर्स इन-क्लास कॉन्स्ट परिभाषाओं का समर्थन नहीं करते हैं, जैसा कि आप अपने प्रश्न में कहते हैं।इसलिए, जब तक आपको संदेह न हो कि आपका कोड पुराने कंपाइलर को पोर्ट किया जाएगा, तो आपको उस कॉन्स का उपयोग करना चाहिए जहां कॉन्स देय है।

1

ठीक है, पोर्टेबिलिटी enum का उपयोग करने के लिए एक अच्छा कारण है। यह बहुत अच्छा है, क्योंकि आपको चिंता करने की ज़रूरत नहीं है कि आपका कंपाइलर "स्थिर कॉन्स इंट एस = 10" का समर्थन करता है या नहीं ...

साथ ही, जहां तक ​​मुझे याद है, स्थैतिक चर कहीं भी परिभाषित किया जाना चाहिए, साथ ही साथ घोषित किया गया है, और enum मूल्य केवल घोषित किया जाना चाहिए।

+0

अभिन्न प्रकार की एक स्थिर स्थिरांक मान को परिभाषित नहीं किया जाना चाहिए यदि घोषणा में एक अभिन्न निरंतर अभिव्यक्ति प्रारंभकर्ता शामिल है, लेकिन नियम बहुत अस्पष्ट हैं। मेरा जवाब देखें –

5

enum का उपयोग एक फायदा है। एक enum प्रकार, एक प्रकार है, इसलिए यदि आप उदाहरण के लिए परिभाषित,:

enum EnumType { EnumValue1 = 10, EnumValue2 = 20 ... }; 

और आप की तरह एक समारोह है:

void Function1(EnumType Value) 

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

void Function1(int Value) 

के समारोह को बदलते हैं।

एनम प्रकार संबंधित कॉन्स-वैल्यू समूहबद्ध करने के लिए अच्छे हैं। केवल एक कॉन्स वैल्यू के लिए, मुझे कोई फायदा नहीं दिख रहा है।

2

उन दोनों के बीच एक अंतर है। जहां तक ​​मुझे पता है कि Enums के पास एक एड्रेस नहीं है। स्थिर कॉन्स इंक हालांकि करते हैं। तो अगर कोई स्थिर स्थिर int का पता लगाता है, तो वह स्थिरता को रोकता है, वह मूल्य को संशोधित कर सकता है (हालांकि संकलक परिवर्तन को अनदेखा कर सकता है क्योंकि वह सोचता है कि वह इसका आधार है)। यह निश्चित रूप से शुद्ध बुराई है और आपको यह नहीं करना चाहिए - लेकिन संकलक इसे रोक नहीं सकता है। यह enums के साथ नहीं हो सकता है।

और निश्चित रूप से - यदि आप (किसी कारण से) उस कॉस्ट के पते की आवश्यकता है, तो आपको स्थिर कॉन्स int की आवश्यकता है।

संक्षेप में enum एक रैवल्यू है जबकि स्थैतिक int एक lvalue है। अधिक जानकारी के लिए http://www.embedded.com/story/OEG20011129S0065 देखें।

+0

ग्राहक परिभाषा के बिना 'स्थिर स्थिर int 'सदस्य चर का पता नहीं ले पाएगा। हालांकि, रावल्यू/लैवल्यू भेद स्थान पर है। –

+0

ग्राहक नहीं करेगा - लेकिन कक्षा को बनाए रखने और बाद में कोड जोड़ने वाला कोई भी व्यक्ति नहीं। –

संबंधित मुद्दे

 संबंधित मुद्दे