2010-09-06 15 views
8

एक सहकर्मी को नियमित रूप से कुछ इस तरह लिखते हैं:यदि कोई कॉल कॉल दो कॉलन के साथ शुरू होता है तो इसका क्या अर्थ है?

::someObject->someMethod(anAttribute, anotherAttribute); 

someObject एक वैश्विक चर रहा है।
उन दो कोलन मेरे लिए अजीब लगते हैं। कोड संकलित करता है और उनके बिना बस ठीक चलाता है।

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

क्या आप उन कॉलोनों के बारे में कुछ प्रकाश डाल सकते हैं और क्या वे आवश्यक हैं?

+5

मैं हमेशा ग्लोबल्स वर्रों पर जोर देता हूं। यहां तक ​​कि यदि एक ही नाम के साथ स्थानीय वार्स निषिद्ध थे। बी/सी ग्लोबल्स ** ईविल ** –

+0

'::' का उपयोग वैश्विक चर तक ही सीमित नहीं है; यह वैश्विक कुछ भी संदर्भित करता है। इसलिए, यदि आपके पास विरासत 'स्ट्रिंग' क्लास है, तो इसे ':: स्ट्रिंग' के रूप में संदर्भित करने के लिए सलाह दी जाती है और इसलिए' std :: string' के साथ भ्रम को रोकें। – MSalters

+0

@MSalters: b.t.w. क्या होगा यदि मैं 'नेमस्पेस std' का उपयोग करके टाइप करूंगा और फिर' :: स्ट्रिंग स्ट्र 'टाइप करूं? 'Str' का प्रकार क्या होगा? –

उत्तर

8

आपका सहकर्मी सही है। आप वास्तव में एक स्थानीय someObject जो कि दायरे के भीतर वैश्विक someObject छिपाने परिभाषित कर सकते हैं:

SomeClass* someObject = ...; 

// here the global object is visible 
someObject->someMethod(anAttribute, anotherAttribute); // calls the global object 

void someMethod() { 
    SomeClass* someObject = ...; 
    // here the local object hides the global 
    ::someObject->someMethod(anAttribute, anotherAttribute); // calls the global object 
    someObject->someMethod(anAttribute, anotherAttribute); // calls the local object 
} 

// here again only the global object is visible 
someObject->someMethod(anAttribute, anotherAttribute); // calls the global object 

कार्यक्षेत्र अन्य कार्यक्षेत्रों के भीतर एम्बेड किया जा सकता रिकर्सिवली, इस प्रकार आप वैश्विक दायरे के भीतर एक नाम स्थान, एक namespace के भीतर एक वर्ग हो सकता है, एक कक्षा के भीतर आंतरिक वर्ग, एक आंतरिक वर्ग के भीतर एक विधि, विधि के भीतर एक ब्लॉक ... आदि। और इनमें से किसी भी स्कोप में समान नामों के चर/कक्षा/विधियां/... हो सकते हैं। तो यह पहचानना कि एक विशिष्ट नाम किस इकाई का जिक्र कर रहा है वह सी ++ में एक छोटा कार्य नहीं है। इसे name lookup के रूप में जाना जाता है।

संक्षेप में, जब भी कंपाइलर का नाम मिलता है, तो यह उस नाम को सबसे ऊपर के दायरे से शुरू करता है। अर्थात। someMethod के अंदर, someObject नाम स्थानीय रूप से परिभाषित वस्तु से मेल खाता है। ::someObject इस डिफ़ॉल्ट व्यवहार को ओवरराइड करता है और केवल बाहरी (वैश्विक) दायरे में कंपाइलर खोज बनाता है, इस प्रकार यह स्थानीय के बजाय वैश्विक वस्तु पाता है।

3

सहकर्मी का दावा है कि उन कोलन someObject स्पष्ट रूप से वैश्विक बनाने के लिए और इस तरह एक संभव स्थानीय someObject के साथ भ्रम को रोकने के।

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

मुझे लगता है कि होता है कि आप स्थानीय रूप से someObject परिभाषित करने में सक्षम नहीं हो सकता है अगर यह पहले से ही विश्व स्तर पर परिभाषित किया गया था?

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

:: के लाभों के बारे में

, पर विचार करें:

namespace X 
{ 
    void fn() { 
     rip(data, bytes); // MP3 rip this data 
    } 
} 

... तो fn() जरूरतों नाम स्थान को Y जल्दी से स्थानांतरित करने की ...

namespace Y 
{ 
    void rip(const char* message, int exit_code); /* for fatal errors */ 
    ... 
} 

... एक आकस्मिक copy- वाई के गले में पेस्ट आसानी से अनदेखा कर सकता है कि लॉग उसी वैश्विक फ़ंक्शन से मेल नहीं खाएगा जब यह नामस्थान एक्स में था, लेकिन - जैसा कि सचित्र - कार्यक्षमता स्पष्ट रूप से भिन्न हो सकती है :-)।

आप प्रत्येक नामस्थान, वर्ग/संरचना और पेड़ बनाने वाले कार्यों के बारे में सोच सकते हैं, जहां प्रत्येक स्तर को विशिष्ट रूप से कुंजी (यानी समान नामस्थान में समान नामित कक्षाएं) नहीं होनी चाहिए, लेकिन निर्णायक हमेशा एक दूसरे से स्वतंत्र होते हैं और उनके पूर्वजों। कई लोगों को एक बड़ी समस्या पर एक साथ काम करने के लिए स्वतंत्र रूप से भिन्न होने की स्वतंत्रता बढ़ाना आवश्यक है।

आप कुछ प्रकाश क्या पर उन कोलन मतलब है और वे आवश्यक हैं या नहीं डाला सकता है?

इस विशिष्ट उपयोग में, :: शायद सख्ती से जरूरी नहीं है। यह थोड़ा संरक्षण जोड़ता है, लेकिन बाद में वैरिएबल को एक और स्थानीय दायरे में स्थानांतरित करना कठिन बनाता है - हालांकि यह इतना महत्वपूर्ण नहीं है क्योंकि संकलक आपको उन स्थानों के बारे में बताएगा जो x के बाद x को स्थानांतरित कर रहे हैं।

4

आप वैश्विक स्तर पर होने के बावजूद स्थानीय रूप से कुछ ऑब्जेक्ट को परिभाषित कर सकते हैं। दो चरों के अलग-अलग दायरे हैं, इसलिए संकलक जानता है कि दोनों के बीच एक अंतर है, और डबल कॉलन आपको वैश्विक को संदर्भित करने देते हैं।

यह नामस्थान के बाहर कक्षाओं पर भी लागू होता है; यानी, कक्षा बार :: फू से कक्षा फू को संदर्भित करने के लिए, आप उस कंपाइलर को बताने के लिए :: Foo का उपयोग करते हैं, जिसे आप नामस्थान में नहीं है।

#include<stdio.h> 

int someInt = 4; 

int main() { 
     int someInt = 5; 
     printf("%d", someInt+::someInt); 
     return 0; 
} 

आप संकलन और कोड के उस टुकड़े चलाते हैं, यह उत्पादन 9.

1

बस एक छोटी सी अन्य सभी अच्छा अंक है जो करने के लिए पर जोड़ देगा:

यहाँ एक उदाहरण है कि यह काम कर रहा से पता चलता है प्रतिक्रिया में आओ।

मूल रूप से :: वैश्विक नामस्थान में योग्य नाम लुकअप का आह्वान करता है। हालांकि यह विशेष रूप से निर्देशों का उपयोग करके अंधाधुंध के चेहरे में समस्या मुक्त होने की गारंटी नहीं है।

दिखाया गया कोड योग्य नाम लुकअप की एक महत्वपूर्ण संपत्ति दिखाता है। यहां बिंदु यह है कि वैश्विक नम्सस्पेस में निर्देशों का उपयोग करके मनोनीत नामस्थानों की खोज की जाती है। हालांकि नामस्थानों में निर्देशों का उपयोग करना जिनके नाम की खोज की जा रही है, छोड़ दी गई हैं।

namespace Z{ 
     void f(){cout << 1;} 
    } 

    namespace Y{ 
     void f(){cout << 2;} 
     using namespace Y;  // This namespace is not searched since 'f' is found in 'Y' 
    } 

#if 0 
    namespace Z{ 
     void f(){cout << 3;} 
     using namespace Y;  // This namespace is not searched since 'f' is found in 'Y' 
    } 
    using namespace Z; 
#endif 
    using namespace Y; 

    int main(){ 
     ::f();     // Prints 2. There is no ambiguity 
    } 

दिखाए गए कोड में, यदि #if निर्देश के साथ लाइनों सक्षम होते हैं, वहाँ नाम 'एफ' को दूर करने में एक अस्पष्टता है।

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