C ++ में enum घोषित करते समय आप typedef का उपयोग क्यों करते हैं?


183

मैंने वर्षों में कोई C ++ नहीं लिखा है और अब मैं इसमें वापस आने की कोशिश कर रहा हूं। मैं फिर इस पार भाग गया और हार मानने के बारे में सोचा:

typedef enum TokenType
{
    blah1   = 0x00000000,
    blah2   = 0X01000000,
    blah3   = 0X02000000
} TokenType;

यह क्या है? typedefयहाँ कीवर्ड का उपयोग क्यों किया जाता है? TokenTypeइस घोषणा में दो बार नाम क्यों दिखाई देता है? शब्दार्थ इससे अलग कैसे हैं:

enum TokenType
{
    blah1 = 0x00000000,
    blah2=0x01000000,
    blah3=0x02000000
};

जवाबों:


156

सी में, अपने एनम को पहला तरीका घोषित करने से आप इसका उपयोग कर सकते हैं:

TokenType my_type;

यदि आप दूसरी शैली का उपयोग करते हैं, तो आपको अपना चर इस तरह घोषित करने के लिए मजबूर किया जाएगा:

enum TokenType my_type;

जैसा कि दूसरों ने उल्लेख किया है, इससे C ++ में कोई फर्क नहीं पड़ता है। मेरा अनुमान है कि या तो जिसने यह लिखा है, वह दिल से एक सी प्रोग्रामर है, या आप सी कोड को C ++ के रूप में संकलित कर रहे हैं। किसी भी तरह से, यह आपके कोड के व्यवहार को प्रभावित नहीं करेगा।


12
आपका प्रश्न केवल C के लिए सही है, लेकिन C ++ के लिए नहीं। C ++ में एनम और स्ट्रक्चर्स का उपयोग सीधे तौर पर किया जा सकता है जैसे कि एक टंकण था।
डेविड रॉड्रिग्ज - 22

7
ठीक है, हाँ, लेकिन यह उस वास्तविक प्रश्न का उत्तर देता है जो पूछा गया था कि वास्तव में "इसका क्या अर्थ है?"
BobbyShaftoe

तो क्या यह तकनीकी रूप से एक टाइप्डेफ या एनम है?
मीक

5
यह दोनों है। आप यह भी कह सकते हैं: enum TokenType_ {...}; typedef enum TokenType_ TokenType;
रयान फॉक्स

उत्तर पूर्ण है, लेकिन मेरा मानना ​​है कि बिंदु यह है कि टोकन टाइप; एनम घोषणा के बाद प्रकार नाम घोषित कर रहा है। तो उत्तर 100% पूर्ण नहीं है 'पहला तरीका' घोषित करना बीओटीएच को एक Enum और एक नया टाइपनेम जो कि सिनेमैक्स के एक ब्लॉब में एनम को निर्दिष्ट करता है। तो उत्तर उपयोगी था, लेकिन मुझे लगता है कि थोड़ा सुधार किया जा सकता है। शायद मैं वोट के लिए बहुत कठोर था। तो मैंने उस सब के बाद उसे उखाड़ फेंका। अगर मुझे वाकई खुद पर यकीन था, तो मैं संपादन / उत्तर को बेहतर बनाने के लिए एक स्वैग ले लूंगा ... लेकिन यह एक बहुत अच्छा जवाब है
रॉस यंगब्लड

97

यह एक सी विरासत है, सी में, यदि आप करते हैं:

enum TokenType
{
    blah1   = 0x00000000,
    blah2   = 0X01000000,
    blah3   = 0X02000000
};

आपको इसका उपयोग कुछ इस तरह करना होगा:

enum TokenType foo;

लेकिन अगर आप ऐसा करते हैं:

typedef enum e_TokenType
{
    blah1   = 0x00000000,
    blah2   = 0X01000000,
    blah3   = 0X02000000
} TokenType;

आप घोषित कर सकेंगे:

TokenType foo;

लेकिन सी ++ में, आप केवल पूर्व परिभाषा का उपयोग कर सकते हैं और इसका उपयोग कर सकते हैं जैसे कि यह सी टाइपडिफ में था।


1
आप जो कहते हैं वह सी में सच है। सी ++ में यह सच नहीं है।
जोनाथन लेफ़लर

49
क्या मैंने अपने अंतिम वाक्य में नहीं कहा है?
चटाई

2
@mat मैंने अंतिम वाक्य के बारे में आपकी टिप्पणी को गलत ठहराया है, लेकिन निष्पक्ष होने के लिए यह खराब रूप से शब्दबद्ध और भ्रमित करने वाला है।
AR

20

आपको इसे करने की आवश्यकता नहीं है। C (C ++ नहीं) में आपको एन्यूमरेटेड प्रकार के डेटा तत्व को संदर्भित करने के लिए Enum Enumname का उपयोग करना आवश्यक था । यह आसान बनाने के लिए आप की अनुमति दी गई typedef एक ही नाम डेटा प्रकार के लिए यह।

typedef enum MyEnum { 
  //...
} MyEnum;

अनुमत कार्यों के रूप में परिभाषित करने के लिए एनम के एक पैरामीटर ले रहा है

void f( MyEnum x )

इसके बजाय लंबे समय तक

void f( enum MyEnum x )

ध्यान दें कि टाइपनेम का नाम एनम के नाम के बराबर होने की आवश्यकता नहीं है। ऐसा ही स्ट्रक्चर्स के साथ होता है।

सी ++ में, दूसरी ओर, इसकी आवश्यकता नहीं है, क्योंकि एनम, कक्षाएं और संरचनाएं उनके नाम से सीधे टाइप के रूप में एक्सेस की जा सकती हैं।

// C++
enum MyEnum {
   // ...
};
void f( MyEnum x ); // Correct C++, Error in C

वास्तव में मुझे लगता है कि यह आम तौर पर स्वीकृत एक से बेहतर उत्तर हो सकता है, क्योंकि यह स्पष्ट रूप से बताता है "क्यों" यह अलग है।
रॉस यंगब्लड

11

सी में, यह अच्छी शैली है क्योंकि आप एक एनुम के अलावा कुछ को प्रकार बदल सकते हैं।

typedef enum e_TokenType
{
    blah1   = 0x00000000,
    blah2   = 0X01000000,
    blah3   = 0X02000000
} TokenType;

foo(enum e_TokenType token);  /* this can only be passed as an enum */

foo(TokenType token); /* TokenType can be defined to something else later
                         without changing this declaration */

C ++ में आप एनम को परिभाषित कर सकते हैं ताकि यह C ++ या C के रूप में संकलित हो जाए।


क्या आपके कहने का मतलब नहीं है In C++ you can *typedef* the enum so that it will compile as C++ or C.? आप ने कहा: In C++ you can define the enum so that it will compile as C++ or C.सूचना कैसे मैं अपने बदल defineकरने के लिए typedef। अच्छा ... मुझे लगता है कि typedefआईएनजी परिभाषित कर रहा है
गेब्रियल स्टेपल्स

6

सी। से होल्डओवर।


डननो कि 'शुरुआती' क्वालीफायर प्रासंगिक है; आप अभी भी लिखेंगे कि यदि आप बिना एनम उपसर्ग के टाइप नाम का उपयोग करना चाहते हैं।
जोनाथन लेफ़लर

1
सच। मैं इसे डिलीट कर दूंगा। मैंने लंबे समय तक सी कल्पना का पालन नहीं किया है। मैं अपने लिए c / c ++ भेद ... -1 की जांच करने में बहुत आलसी था।
टिम

6

कुछ लोगों का कहना है कि सी में नाम स्थान नहीं है लेकिन यह तकनीकी रूप से सही नहीं है। इसके तीन हैं:

  1. टैग ( enum, union, और struct)
  2. लेबल
  3. (बाकि सब कुछ)

typedef enum { } XYZ;एक अनाम गणना की घोषणा करता है और इसे नाम के साथ वैश्विक नामस्थान में आयात करता है XYZ

typedef enum ABC { } XYZ;ABCटैग नाम स्थान में एक एनुम घोषित करता है , फिर इसे वैश्विक नामस्थान में आयात करता है XYZ

कुछ लोग अलग-अलग नामस्थानों से परेशान नहीं करना चाहते हैं ताकि वे सब कुछ टाइप करें। दूसरों को कभी भी टाइप नहीं किया क्योंकि वे नाम स्थान चाहते हैं।


यह बिल्कुल सटीक नहीं है। संरचना, यूनियन और एनम को टैग नाम से संदर्भित किया जाता है (जब तक कि अनाम नहीं है, जैसा कि आपने उल्लेख किया है)। प्रकार और टैग के लिए अलग नामस्थान हैं। आपके पास एक टैग के समान सटीक नाम के साथ एक प्रकार हो सकता है और ठीक संकलन हो सकता है। हालाँकि, अगर किसी एनुम में स्ट्रक्चर के समान टैग होता है, तो यह एक कंपाइल एरर है, जैसे 2 कॉम्प्लेक्स या 2 एनाम, जिसमें एक ही टैग होगा। आपका यह भी भूल गया कि गोटो के लिए लेबल एक अलग नामस्थान हैं। एक लेबल एक टैग, या एक पहचानकर्ता के रूप में एक ही नाम हो सकता है, लेकिन एक प्रकार नहीं है, और एक पहचानकर्ता एक टैग के समान नाम हो सकता है, लेकिन एक प्रकार नहीं।
रिच जाह्न

3

यह पुराने जैसा है, लेकिन वैसे भी, मुझे आशा है कि आप उस लिंक की सराहना करेंगे जो मैं टाइप करने वाला हूं क्योंकि मैंने इसकी सराहना की थी जब मैं इस साल की शुरुआत में आया था।

यहाँ यह है । मुझे उस स्पष्टीकरण को उद्धृत करना चाहिए जो मेरे दिमाग में हमेशा रहता है जब मुझे कुछ बुरा टाइपिडिफ्स पकड़ना पड़ता है:

परिवर्तनीय घोषणाओं में, प्रस्तुत नाम इसी प्रकार के उदाहरण हैं। [...] हालांकि, जब typedefकीवर्ड घोषणा से पहले आता है, तो प्रस्तुत नाम संबंधित प्रकार के उपनाम हैं

जैसा कि कई लोगों ने पहले कहा था, C ++ में एनमों की घोषणा करने वाले टाइपफीड्स का उपयोग करने की कोई आवश्यकता नहीं है । लेकिन यह है कि typedef वाक्यविन्यास की व्याख्या! मुझे आशा है कि यह मदद करता है (शायद ओपी नहीं, क्योंकि यह लगभग 10 साल है, लेकिन कोई भी जो इस तरह की चीजों को समझने के लिए संघर्ष कर रहा है)।


1

कुछ सी कोडवर्ड गाइड में टाइपडीफ संस्करण को "स्पष्टता" और "सरलता" के लिए पसंद किया जाता है। मैं असहमत हूं, क्योंकि टाइपडिफ घोषित वस्तु की वास्तविक प्रकृति को मानता है। वास्तव में, मैं टाइपफीड्स का उपयोग नहीं करता हूं क्योंकि सी चर घोषित करते समय मैं इस बारे में स्पष्ट होना चाहता हूं कि वास्तव में वस्तु क्या है। यह विकल्प खुद को तेजी से याद रखने में मदद करता है कि कोड का एक पुराना टुकड़ा वास्तव में क्या करता है, और भविष्य में कोड को बनाए रखने पर दूसरों की मदद करेगा।


1

"क्यों" प्रश्न (जो मौजूदा उत्तर शीर्ष इस पुराने प्रश्न द्वारा आश्चर्यजनक रूप से अनदेखा किया गया है) का वास्तविक उत्तर यह है कि यह enumघोषणा संभवतः एक हेडर फ़ाइल में स्थित है, जिसका उद्देश्य C और C ++ कोड दोनों के रूप में क्रॉस-कंपाइल करने योग्य है (अर्थात C और C ++ क्रियान्वयन फ़्यूल्स दोनों में शामिल)। ऐसी हेडर फाइलें लिखने की कला लेखक की उन भाषा विशेषताओं का चयन करने की क्षमता पर निर्भर करती है जिनका दोनों भाषाओं में उचित संगत अर्थ होता है।

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