2010-01-11 20 views
45

मैं अलग-अलग निरंतर घोषणाओं और सी ++ में परिभाषा विकल्पों के लाभ/हानिकारक के बारे में उत्सुक हूं। लंबे समय के लिए, मैं सिर्फ उन्हें हेडर फाइल के शीर्ष पर वर्ग परिभाषा से पहले घोषित किया गया है:सी ++ में कक्षा स्कोप स्थिरांक घोषित/परिभाषित करने के लिए कहां?

//.h 
const int MyConst = 10; 
const string MyStrConst = "String"; 
class MyClass { 
... 
}; 

इस वैश्विक नामस्थान (जो मैं जानता हूँ कि एक बुरी बात है को प्रदूषित करता है, लेकिन कभी नहीं पाया है कारणों की एक कपड़े धोने की सूची क्यों खराब है), स्थिरांक अभी भी अलग-अलग अनुवाद इकाइयों तक पहुंच जाएंगे, इसलिए जिन फ़ाइलों में इस हेडर को शामिल नहीं किया गया है, उन्हें इन स्थिरांक तक पहुंच नहीं होगी। लेकिन यदि आप अन्य वर्ग एक ही नाम के निरंतर परिभाषित करते हैं, तो आप नाम टकराव प्राप्त कर सकते हैं, जो तर्कसंगत रूप से बुरी चीज नहीं है क्योंकि यह उस क्षेत्र का एक अच्छा संकेत हो सकता है जिसे दोबारा किया जा सकता है।

हाल ही में, मैंने तय कर लिया है कि यह वर्ग परिभाषा के ही अंदर वर्ग विशिष्ट स्थिरांक घोषित करने के लिए बेहतर होगा:

//.h 
class MyClass { 
    public: 
     static const int MyConst = 10; 
... 
    private: 
     static const string MyStrConst; 
... 
}; 
//.cpp 
const string MyClass::MyStrConst = "String"; 

निरंतर की दृश्यता निरंतर केवल आंतरिक रूप से करने के लिए प्रयोग किया जाता है जो इस पर निर्भर समायोजित किया जाएगा वर्ग या वर्ग का उपयोग करने वाली अन्य वस्तुओं के लिए आवश्यक है। यही वह है जो मैं सोच रहा हूं कि अभी सबसे अच्छा विकल्प है, मुख्य रूप से क्योंकि आप कक्षा में निजी वर्ग स्थिरांक को निजी रख सकते हैं और सार्वजनिक स्थिरांक का उपयोग करके किसी भी अन्य वर्ग में निरंतर स्रोत के स्रोत का अधिक विस्तृत संदर्भ होगा (उदाहरण के लिए MyClass: : MyConst)। यह वैश्विक नामस्थान को प्रदूषित नहीं करेगा। हालांकि इसमें सीपीपी फ़ाइल में गैर-अभिन्न प्रारंभिक आवश्यकता की कमी है।

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

बस राय और संभवतः अन्य विकल्प मैं अभी तक नहीं माना जाता था की तलाश में।

उत्तर

1

आप जब तक कि वे शीर्ष लेख में संदर्भित नहीं हैं, C++ फ़ाइल में वैश्विक रूप में उन्हें घोषणा कर सकते हैं। फिर वे उस वर्ग के लिए निजी हैं और वैश्विक नामस्थान को प्रदूषित नहीं करेंगे।

+0

हां, लेकिन आप 'static' या इस मामले में एक गुमनाम नाम स्थान का उपयोग करने के - अगर आप नहीं करते हैं, कुछ कार्यान्वयन में आप वैश्विक नामस्थान को दूषित लिंकर द्वारा उपयोग किया जाता है और लिंकिंग पर नाम संघर्ष प्राप्त होता है ... – hjhill

9

वैश्विक नामस्थान का प्रदूषण खराब है क्योंकि कोई (उदाहरण के लिए आपके द्वारा उपयोग की जाने वाली लाइब्रेरी का लेखक) किसी अन्य उद्देश्य के लिए MyConst नाम का उपयोग करना चाह सकता है। यह गंभीर समस्याओं (पुस्तकालयों है कि एक साथ आदि का उपयोग नहीं किया जा सकता है) को जन्म दे सकता

आपका दूसरा समाधान स्पष्ट रूप से सबसे अच्छा है, तो स्थिरांक एकल वर्ग से जुड़े हुए हैं है। यदि यह इतना आसान नहीं है (आपके प्रोग्राम में कक्षा के संबंध में भौतिक या गणित स्थिरांक के बारे में सोचें), नामस्थान समाधान उससे बेहतर है। Btw: अगर आप पुराने सी ++ compilers करने के लिए संगत होना चाहिए, याद उनमें से कुछ एक हेडर फाइल में अभिन्न आरंभीकरण उपयोग नहीं कर सकते हैं - आप सी ++ फ़ाइल में प्रारंभ या इस मामले में वर्ष enum चाल का उपयोग करना चाहिए।

मुझे लगता है कि स्थिरांक के लिए कोई बेहतर विकल्प हैं - कम से कम इस समय एक के बारे में सोच नहीं सकते हैं ...

2

व्यक्तिगत तौर पर मैं अपने दूसरे दृष्टिकोण का उपयोग करें; मैंने इसे वर्षों से इस्तेमाल किया है, और यह मेरे लिए अच्छा काम करता है।

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

35

आपका दावा है कि एक स्थिर वर्ग सदस्य के रूप में एक गैर-अभिन्न निरंतर घोषित करना " सीपीपी फ़ाइल में गैर-अभिन्न प्रारंभिक आवश्यकता की क्षति का नुकसान है "कहने के लिए बिल्कुल ठोस नहीं है।इसे सीपीपी फ़ाइल में परिभाषा की आवश्यकता होती है, लेकिन यह "नुकसान" नहीं है, यह आपके इरादे का विषय है। सी ++ में नाम स्थान स्तरीय const वस्तु, डिफ़ॉल्ट रूप से आंतरिक संबंध है, जिसका अर्थ है कि अपने मूल संस्करण में घोषणा

const string MyStrConst = "String"; 

यानी यह हर अनुवाद इकाई में एक स्वतंत्र MyStrConst वस्तु परिभाषित करेगा

static const string MyStrConst = "String"; 

के बराबर है जिसमें यह हेडर फ़ाइल शामिल है। क्या आप इससे जागरुक हैं? क्या यह आपका इरादा था या नहीं?

किसी भी मामले में, यदि आप विशेष रूप से हर अनुवाद इकाई में एक अलग वस्तु की जरूरत नहीं है, अपने मूल उदाहरण में MyStrConst निरंतर की घोषणा एक अच्छा अभ्यास नहीं है। आम तौर पर, आप केवल हेडर फाइल

extern const string MyStrConst; 

में एक गैर को परिभाषित घोषणा रख दिया और सीपीपी फ़ाइल

const string MyStrConst = "String"; 

इस प्रकार में एक परिभाषा प्रदान सुनिश्चित करें कि पूरे कार्यक्रम एक ही स्थिर वस्तु का उपयोग करता है बनाने चाहते हैं । दूसरे शब्दों में, जब गैर-अभिन्न स्थिरांक की बात आती है, तो सामान्य अभ्यास उन्हें सीपीपी फ़ाइल में परिभाषित करना है। तो, इस पर ध्यान दिए बिना कि आप इसे कैसे घोषित करते हैं (कक्षा या बाहर) आपको आमतौर पर सीपीपी फ़ाइल में इसे परिभाषित करने के "नुकसान" से निपटना होगा। बेशक, जैसा कि मैंने उपरोक्त कहा है, नामस्थान स्थिरांक के साथ आप अपने पहले संस्करण में जो कुछ भी प्राप्त कर सकते हैं, उससे दूर हो सकते हैं, लेकिन यह केवल "आलसी कोडिंग" का एक उदाहरण होगा।

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

पीएस एक्सेस विनिर्देशक (public, protected, private) नाम के दृश्यता को नियंत्रित न करें। वे केवल पहुंच क्षमता पर नियंत्रण करते हैं। नाम किसी भी मामले में दिखाई देता है।

+0

क्या मैं पूछ सकता हूं दृश्यता और अभिगम्यता के बीच क्या अंतर है? मुझे लगता है कि वे वही हैं, क्या आप एक उदाहरण दे सकते हैं? – toolchainX

+0

@toolchainX: उदाहरण: एक सदस्य फ़ंक्शन निजी हो सकता है, लेकिन फ़ंक्शन संकलक को 'दृश्यमान' हो सकता है, इस अर्थ में कि हम मानते हैं कि परिभाषा मौजूद है और संकलक इसे 'देख' सकता है। कंपाइलर बस कोई एक्सेस [कंपाइलर त्रुटि] लागू करता है। परिभाषा को हटाने या परिभाषा को कहीं भी 'छुपा' रखने से इन शर्तों में कार्य 'दृश्यमान' नहीं होगा - यहां तक ​​कि सदस्य कार्यों तक भी - पहुंच [लिंक त्रुटि] के बावजूद। – wardw

+0

इसे .cpp फ़ाइल में डालने का नुकसान होगा क्योंकि संकलक निरंतर इनलाइन नहीं कर सकता क्योंकि यह कंपाइलर की अनुवाद इकाई में नहीं है। यदि स्थिरता केवल एक वर्ग को पूर्णांक लपेटती है, तो यह हेडर फ़ाइल में होना बेहतर होगा ताकि संकलक जानता हो कि यह सभी संकलन इकाइयों में क्या मूल्य है। – qbt937

5

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

#define read _read 

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

आपका दूसरा समाधान बहुत उचित है क्योंकि यह चर को दायरे में रखता है। ऐसा कोई कारण नहीं है कि इसे कक्षा के साथ जोड़ा जाना है, और यदि मुझे कक्षाओं के बीच स्थिरांक साझा करने की आवश्यकता है तो मैं अपने नामस्थान और हेडर फ़ाइल में स्थिरांक घोषित करूंगा। यह संकलन समय के लिए अच्छा नहीं है, लेकिन कभी-कभी यह आवश्यक है।

मैंने लोगों को अपनी कक्षा में स्थिरांक भी देखा है, जिसे सिंगलटन के रूप में कार्यान्वित किया जा सकता है। यह मेरे लिए इनाम के बिना काम लगता है, भाषा आपको स्थिरांक घोषित करने के लिए कुछ सुविधाएं प्रदान करती है।

2

यदि केवल एक वर्ग इन स्थिरांकों का उपयोग करने जा रहा है, तो उन्हें कक्षा के शरीर के अंदर static const घोषित करें। यदि संबंधित वर्गों का एक समूह स्थिरांक का उपयोग करने जा रहा है, तो उन्हें या तो कक्षा/संरचना के अंदर घोषित करें जो केवल स्थिरांक और उपयोगिता विधियों या समर्पित नामस्थान के अंदर रखता है। उदाहरण के लिए,

namespace MyAppAudioConstants 
{ 
    //declare constants here 
} 

वे पूरे आवेदन (या इसके पर्याप्त मात्रा) द्वारा इस्तेमाल किया स्थिरांक हैं, तो उन्हें एक नाम स्थान के अंदर एक ऐसा हेडर है (अनुमान से या स्पष्ट) हर जगह शामिल में घोषणा करते हैं।

namespace MyAppGlobalConstants 
{ 
    //declare constants here 
} 
1

वैश्विक नामस्थान प्रदूषित न करें, स्थानीय प्रदूषित करें।

namespace Space 
    { 
    const int Pint; 
    class Class {}; 
    }; 

लेकिन व्यावहारिक रूप से ...

class Class 
    { 
    static int Bar() {return 357;} 
    }; 
संबंधित मुद्दे