2010-03-23 14 views
114

के तहत एक enum घोषित करना निम्नलिखित कोड स्निपेट में, Color enum को Car कक्षा के भीतर घोषित किया गया है ताकि एनम के दायरे को सीमित किया जा सके और वैश्विक नामस्थान को "प्रदूषित" न करने का प्रयास किया जा सके।कक्षा

class Car 
{ 
public: 

    enum Color 
    { 
     RED, 
     BLUE, 
     WHITE 
    }; 

    void SetColor(Car::Color color) 
    { 
     _color = color; 
    } 

    Car::Color GetColor() const 
    { 
     return _color; 
    } 

private: 

    Car::Color _color; 

}; 

(1) इस Color enum के दायरे को सीमित करने के लिए एक अच्छा तरीका है? या, क्या मुझे इसे Car कक्षा के बाहर घोषित करना चाहिए, लेकिन संभवतः अपने नामस्थान या संरचना के भीतर? मैं आज इस लेख में आया हूं, जो उत्तरार्द्ध की वकालत करता है और enums के बारे में कुछ अच्छे बिंदुओं पर चर्चा करता है: http://gamesfromwithin.com/stupid-c-tricks-2-better-enums

(2) इस उदाहरण में, जब भीतर वर्ग काम कर रहा है, यह सबसे अच्छा Car::Color के रूप में enum कोड करने के लिए है, या बस Color पर्याप्त होगा? (मुझे लगता है कि पूर्व बेहतर है, अगर किसी अन्य Color enum वैश्विक नामस्थान में घोषित किया गया है। इस तरह, कम से कम, हम इस बात के बारे में स्पष्ट हैं कि हम संदर्भ दे रहे हैं।)

उत्तर

69
  1. तो Color कुछ है कि उसके बाद इस तरह आप अपने दायरा सीमित होता है सिर्फ Car रों के लिए विशिष्ट है। यदि आपके पास अन्य Color enum है जो अन्य वर्गों का उपयोग करते हैं तो आप इसे वैश्विक बना सकते हैं (या कम से कम Car)।

  2. इससे कोई फर्क नहीं पड़ता। यदि कोई वैश्विक है तो स्थानीय अभी भी वैसे भी उपयोग किया जाता है क्योंकि यह वर्तमान दायरे के करीब है। ध्यान दें कि यदि आप कक्षा परिभाषा के बाहर उन फ़ंक्शन को परिभाषित करते हैं तो आपको फ़ंक्शन के इंटरफ़ेस में स्पष्ट रूप से Car::Color निर्दिष्ट करना होगा।

+10

2. हां और नहीं। 'कार :: रंग प्राप्त करें रंग()' लेकिन 'शून्य कार :: सेटकॉलर (रंग सी)' क्योंकि 'सेटकॉलर' में हमारे पास पहले से ही विनिर्देशक है। –

1

यदि आप कोड बना रहे हैं लाइब्रेरी, तो मैं नेमस्पेस का उपयोग करूंगा। हालांकि, आप अभी भी उस नामस्थान के अंदर एक रंग enum हो सकता है। यदि आपको एक ऐसे नाम की आवश्यकता है जो एक सामान्य नाम का उपयोग कर सके, लेकिन अलग-अलग वर्गों के लिए अलग-अलग स्थिरांक हो सकते हैं, तो अपने दृष्टिकोण का उपयोग करें।

6

आम तौर पर, मैं हमेशा अपने enums को struct में डालता हूं। मैंने "उपसर्ग" सहित कई दिशानिर्देश देखे हैं।

enum Color 
{ 
    Clr_Red, 
    Clr_Yellow, 
    Clr_Blue, 
}; 

हमेशा सोचा कि यह C++ की तुलना में C अधिक तरह के दिशानिर्देश देखा (संक्षिप्त नाम की वजह से एक के लिए है और यह भी C++ में नामस्थान की वजह से)।

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

  • नामस्थान
  • structs/वर्गों

मैं व्यक्तिगत रूप से एक struct उपयोग करने के लिए है क्योंकि यह टेम्पलेट के लिए पैरामीटर के रूप में इस्तेमाल किया जा सकता करते हैं प्रोग्रामिंग जबकि नामस्थान का उपयोग नहीं किया जा सकता है।

हेरफेर के उदाहरण में शामिल:

template <class T> 
size_t number() { /**/ } 

जो struct T :)

58

अंदर enum के तत्वों की संख्या देता है मैं दृष्टिकोण (नीचे कोड) निम्नलिखित पसंद करते हैं। यह "नेमस्पेस प्रदूषण" समस्या को हल करता है, लेकिन यह भी अधिक प्रकार का प्रकार है (आप असाइन नहीं कर सकते हैं और दो अलग-अलग समीकरणों की तुलना भी कर सकते हैं, या किसी अन्य अंतर्निर्मित प्रकार आदि के साथ आपकी गणना)।

struct Color 
{ 
    enum Type 
    { 
     Red, Green, Black 
    }; 
    Type t_; 
    Color(Type t) : t_(t) {} 
    operator Type() const {return t_;} 
private: 
    //prevent automatic conversion for any other built-in types such as bool, int, etc 
    template<typename T> 
    operator T() const; 
}; 

उपयोग:

Color c = Color::Red; 
switch(c) 
{ 
    case Color::Red: 
    //некоторый код 
    break; 
} 
Color2 c2 = Color2::Green; 
c2 = c; //error 
c2 = 3; //error 
if (c2 == Color::Red) {} //error 
If (c2) {} error 

मैं सुविधा के लिए मैक्रो बनाते उपयोग:

#define DEFINE_SIMPLE_ENUM(EnumName, seq) \ 
struct EnumName {\ 
    enum type \ 
    { \ 
     BOOST_PP_SEQ_FOR_EACH_I(DEFINE_SIMPLE_ENUM_VAL, EnumName, seq)\ 
    }; \ 
    type v; \ 
    EnumName(type v) : v(v) {} \ 
    operator type() const {return v;} \ 
private: \ 
    template<typename T> \ 
    operator T() const;};\ 

#define DEFINE_SIMPLE_ENUM_VAL(r, data, i, record) \ 
    BOOST_PP_TUPLE_ELEM(2, 0, record) = BOOST_PP_TUPLE_ELEM(2, 1, record), 

उपयोग:

DEFINE_SIMPLE_ENUM(Color, 
      ((Red, 1)) 
      ((Green, 3)) 
      ) 

कुछ उपयोगी संदर्भ:

  1. हर्ब Sutter, Jum Hyslop, C/C++ उपयोगकर्ता जर्नल, 22 (5), मई 2004
  2. हर्ब Sutter, डेविड ई मिलर, Bjarne Stroustrup प्रबलता से टाइप किये Enums (संशोधन 3), जुलाई 2007
+0

मुझे यह पसंद है। यह enum को एक वैध मूल्य के साथ तत्काल करने के लिए मजबूर करता है। मुझे लगता है कि एक असाइनमेंट ऑपरेटर और कॉपी कन्स्ट्रक्टर उपयोगी होगा। इसके अलावा टी_ निजी होना चाहिए। मैक्रोज़ मैं बिना कर सकता हूँ। – jmucchiello

+0

मुझे भी यह पसंद है। संदर्भों के लिए धन्यवाद। – anio

+1

आपने कहा: * "यह भी बहुत अधिक टाइपएफ़ है (आप असाइन नहीं कर सकते हैं और यहां तक ​​कि दो अलग-अलग गणनाओं की तुलना भी कर सकते हैं ..." * आपको क्यों लगता है कि यह एक अच्छी सुविधा है? मुझे लगता है कि अगर (सी 2 == रंग: : लाल) 'उचित है और संकलित होना चाहिए, लेकिन आपके उदाहरण में यह नहीं है। असाइनमेंट के लिए भी तर्क! – Nawaz

66

आजकल - सी ++ 11 का उपयोग - आप इस के लिए enum class उपयोग कर सकते हैं:

enum class Color { RED, BLUE, WHITE }; 

AFAII करता है आप क्या चाहते हैं।