2009-11-15 16 views
5

मैं संभव के रूप में स्थानीय रूप में चीजों को रखने की कोशिश, तो मैं वर्ग दायरे में enums डाल, भले ही वे दो वर्गों (मैं इसे कक्षा में डाल दिया है कि यह साथ "बेहतर हो जाता है"।) यह है के बीच साझा कर रहे हैं बहुत अच्छा काम किया, लेकिन मैंने हाल ही में एक ऐसे मुद्दे में भाग लिया जहां एक गोलाकार निर्भरता तब होगी जब मैं कक्षा के दायरे में enum डाल दिया।Enum scoping मुद्दों

enum कई वर्गों के लिए एक निर्माता तर्क होने जा रहा है, और कक्षा में है (और वर्ग है कि ज्यादातर समझ में आता है उस में होने के लिए) उन वर्गों में शामिल हैं। इस प्रकार, कक्षाओं के लिए कन्स्ट्रक्टर तर्क के रूप में enum का उपयोग करना संभव नहीं है क्योंकि इसका परिणाम गोलाकार निर्भरता में होगा।

बेहतर होगा सिर्फ अपने हेडर फाइल में इस enum डाल करने के लिए, और यदि ऐसा है तो, मैं हेडर फाइल में enums के सभी रखना चाहिए एक समान होना चाहिए? क्या इस मुद्दे के लिए कोई अन्य समाधान हैं (जो तार्किक हैं)?

+0

क्या आपने घोषणाओं को आगे बढ़ाने की कोशिश की है? –

+0

अग्रेषित घोषणाएं आपको केवल प्रकार के नाम तक पहुंचने की अनुमति देती हैं। आप इंटरफ़ेस तक नहीं पहुंच सकते हैं या इसे तत्काल नहीं कर सकते हैं या ऐसा कुछ भी नहीं कर सकते हैं। – Anonymous

उत्तर

3

अगर enum कई वर्गों द्वारा किया जाता है तो मैं कहूंगा कि यह वास्तव में एक भी वर्ग की परिभाषा में लेकिन नाम स्थान में नहीं है जिसमें वे वर्ग रहते हैं।

यह तब तक है जब तक कि एक वर्ग के माध्यम से एक वर्ग के माध्यम से गणना को पारित नहीं किया जा रहा है, इस मामले में यह enum निर्भर वर्ग को तुरंत चालू करने और इसे कक्षा के निर्माता के पैरामीटर के रूप में पास करने के लिए और अधिक समझ सकता है।

+0

आपके द्वारा वर्णित दूसरी बात यह है कि, लेकिन आपके द्वारा वर्णित विधि काम नहीं करेगी। मैंने केवल एक उपयोगिता शीर्षलेख में उपलब्ध enums को बनाने का निर्णय लिया है, जिसने आमतौर पर विधियों का उपयोग किया है। – Anonymous

-2

आप इस तरह enum की घोषणा अग्रेषित करने के लिए कोशिश कर सकते हैं:

enum MyEnum; 
+2

Enums घोषित नहीं किया जा सकता है। – Anonymous

+1

और यदि आप कर सकते हैं, तो भी आप नेस्टेड प्रकार घोषित नहीं कर सकते हैं। या इसके बजाय, आप नेस्टिंग प्रकार की परिभाषा के बिना एक नेस्टेड प्रकार घोषित नहीं कर सकते हैं। –

+0

एक ऐतिहासिक नोट के रूप में, सी ++ 11 के बाद से आप एक 'एनम क्लास' (या 'एनम स्ट्रक्चर') घोषित कर सकते हैं, लेकिन ये पुरानी शैली 'एनम' से अलग हैं। – Quackmatic

1

आप किसी भी वर्ग करता है, तो उसे साझा किया के बाहर enum जगह चाहिए, लेकिन आप अभी भी enum गुंजाइश कर सकते हैं। यह नाम स्थान में रखें तो प्रगणक "रिसाव" नहीं करते हैं, अपनी परियोजना के नाम स्थान को अव्यवस्थित:

namespace Project { // you already have this, right? :) 
    namespace COLOR { // naming styles differ, use what you like 
    enum Color { 
     red, 
     green, 
     blue 
    }; 
    } 
    using COLOR::Color; // now you can use the type 'normally' 

    // examples: 
    struct A { 
    Color c; 
    A() : c(COLOR::red) {} 
    }; 
    void f(Color c) { 
    using namespace COLOR; 
    // inside this function, we no longer have to prefix COLOR:: 
    if (c == green) { 
     go(); 
    } 
    else if (c == red) { 
     stop(); 
    } 
    } 
} 
+0

मुझे 'उपयोग करने की घोषणा = घोषणा का उपयोग करने की कोशिश करनी होगी जैसे कि आप यह देखने के लिए करते हैं कि मुझे यह बेहतर पसंद है या नहीं 'typedef' गड़बड़ जिसका मैं उपयोग कर रहा हूं। मुझे लगता है कि मुझे यह पसंद आएगा (लेकिन enum प्रकार के लिए सभी कैप्स की तुलना में एक अलग नामकरण सम्मेलन का उपयोग कर सकते हैं)। धन्यवाद! –

+0

मैंने सीएपीएस का इस्तेमाल किया क्योंकि ऐसा लगता था कि रंग रंग :: लाल से अधिक इस्तेमाल किया जाएगा, या आप बाद वाले का उपयोग करेंगे और फ़ंक्शन स्कोप पर उपयोग-निर्देश का उपयोग कर सकते हैं। 'typedef रंग :: रंगीन रंग;' रंग :: रंग का उपयोग कर 'के बराबर है; 'यहां। –

2

मैं अक्सर एक नाम स्थान में मेरे enums डाल ग्लोबल नेम स्पेस को अव्यवस्थित से विभिन्न enum मूल्यों को रोकने के लिए। मुझे लगता है कि आप उन्हें कक्षा में डालकर क्या करने की कोशिश कर रहे हैं। लेकिन अगर वे 'फिट' नहीं अच्छी तरह से एक कक्षा में, एक namespace इस उद्देश्य के लिए काफी अच्छी तरह से बस के रूप में काम करता है:

namespace FooSettings 
{ 
    enum FooSettings 
    { 
     foo, 
     bar 
    }; 
} 
typedef enum FooSettings::FooSettings FooSettingsEnum; 


int main() 
{ 
    FooSettingsEnum x = FooSettings::foo; 
}; 

मैं एक संपादक का टुकड़ा है जो दिए गए एक नए गणन के लिए रूपरेखा बस नाम है बनाता है ,

typedef enum FooSettings::FooSettings FooSettingsEnum; 

लाइन है कि एक typedef बनाता है तो यह एक बालक अधिक पठनीय गणन के प्रकार के साथ चर घोषित करने के लिए है भी शामिल है।

मुझे संदेह है कि स्ट्राउस्ट्रप ने गणना के लिए गणित मूल्य नाम बनाए होंगे यदि उसके पास अवसर था, लेकिन सी संगतता ने अपना हाथ मजबूर कर दिया (यह सिर्फ अटकलें है - शायद एक दिन मैं डी & ई में देखूंगा और देख सकता हूं अगर वह कुछ भी उल्लेख करता है)।

+1

मैं व्यक्तिगत रूप से नामस्थान की तुलना में एक संरचना पसंद करता हूं क्योंकि संरचना तब टेम्पलेट्स से छेड़छाड़ की जाती है। –

+0

@Matthieu - एक संरचना का उपयोग करना कभी भी दिमाग में नहीं आया। मैं नहीं कह सकता कि मुझे टेम्पलेट्स के साथ enums में हेरफेर करने में सक्षम नहीं है, लेकिन मैं निश्चित रूप से enum गुंजाइश लपेटने के लिए एक संरचना का उपयोग करने के लिए कोई नकारात्मक पक्ष नहीं देखते हैं। मेरे लिए उपयोग करने के लिए एक और अच्छा विचार है। धन्यवाद। –

+0

मैंने नामस्थान में और एक संरचना में भी enapsulating enums की कोशिश की, और कुछ चीजें एक संरचना के साथ बेहतर काम करते हैं।तो मैं अक्सर निम्नलिखित करता हूं: संरचना MyEnum {enum Values ​​{a, b}; }; टाइपपीफ माईएनम :: मूल्य MyEnum_t; अब मैं एक प्रकार के रूप में enum को संदर्भित करने के लिए 'MyEnum_t' का उपयोग कर सकता हूं, और 'MyEnum :: a',' MyEnum :: b' अपने सदस्यों को संदर्भित करता हूं जैसे कि enum एक कुल प्रकार था। मैंने यहां विशेष नामकरण सम्मेलनों को चुनने से पहले थोड़ी देर का प्रयोग किया था और मैंने समय के साथ उपरोक्त पाया है जितना मैं कर सकता हूं। – Permaquid

7

मैं क्या माइकल और रोजर कर का एक संस्करण का उपयोग करें:

namespace Color 
{ 
    enum Type 
    { 
     red, 
     green, 
     blue 
    }; 
}; 

void paintHouse(Color::Type color) {...} 

main() 
{ 
    paintHouse(Color::red); 
} 

मैं Color::Type लगता है Color::Color या COLOR::Color से खूबसूरत और अधिक आत्म दस्तावेज़ीकृत किया जाना है। यदि आपको Color::Type भी वर्बोज़ मिलता है, तो आप Color::T का उपयोग कर सकते हैं।

मैं अपने गणित मूल्यों का उपसर्ग नहीं करता (यानी COLOR_RED) क्योंकि enum के आसपास नामस्थान प्रभावी ढंग से उपसर्ग बन जाता है।

मैंने अपने स्कॉप्ड स्थिरांक के लिए ALL_CAPS सम्मेलन का उपयोग करना बंद कर दिया है क्योंकि वे सी पुस्तकालयों (उदाहरण के लिए NULL) में मैक्रोज़ के साथ संघर्ष करते हैं। मैक्रो नामस्थान वे में परिभाषित कर रहे हैं में scoped नहीं कर रहे हैं

+0

अब मैं टेम्पलेट पैरामीटर के रूप में इसे पास करने में सक्षम होने के लिए नामस्थान की बजाय संरचना का उपयोग करने के मैथ्यूयू एम के सुझाव को अपनाने पर विचार कर रहा हूं। हालांकि, मैं एक कारण के बारे में नहीं सोच सकता कि मैं रंग :: बजाय टेम्पलेट पैरामीटर के रूप में रंग क्यों पास करूंगा। –

11

सी ++ 11 के बाद से, आप एक enum class उपयोग कर सकते हैं। (या enum struct - एक ही बात अलग घोषित), जहां enum मूल्यों enum के नाम के scoped रहे हैं । उदाहरण के लिए, यहां एक मान्य सी ++ 11 घोषणा है।

enum class token_type { 
    open_paren, 
    close_paren, 
    identifier 
}; 

enum के मूल्यों पर पहुंचने के लिए, हालांकि, आप गुंजाइश इसे सही ढंग से :: ऑपरेटर का उपयोग करना होगा। इसलिए, इस सी ++ 11 में एक वैध काम है:

token_type type = token_type::close_paren; 

लेकिन यह नहीं है:

token_type type = close_paren; 

यह नामकरण संघर्ष को हल करती है, और इसका मतलब है आप कंटेनर नाम स्थान का उपयोग करने की जरूरत नहीं या केवल उन मूल्यों के दायरे को रोकने के लिए संरचना जहां उन्हें नहीं करना चाहिए। इसका मतलब है कि निम्नलिखित enum token_type रूप में एक ही दायरे में मौजूद कर सकते हैं:

enum class other_enum { 
    block, 
    thingy, 
    identifier 
}; 

अब दो मानों दो अलग structs में identifier बुलाया हस्तक्षेप नहीं करेगा।

1

मैं एमिले से सहमत हूं। के रूप में

struct Color 
{ 
    enum Type 
    { 
    red, 
    green, 
    blue 
    }; 
}; 

इस प्रकार मैं आदर्श के बाद से यह पसंद करते हैं मैं एक नाम स्थान का प्रयोग करेंगे एक मॉड्यूल है कि कई वर्गों में शामिल है का प्रतिनिधित्व करने के बजाय सिर्फ देखते हुए एक अन्य विकल्प यदि आप सी ++ 98 उपयोग कर रहे हैं, नाम स्थान के बजाय struct उपयोग करने के लिए है एक enum ...