2012-05-24 16 views
12

निम्नलिखित कोड पर विचार करें:नामस्थान कारण नाम छिपाने का उपयोग कर रहा है?

namespace C { 
    class X {}; 
} 

namespace A { 
    class X {}; 

    namespace B { 
     using namespace C; 

     X x; 
    } 
} 

मैं using namespace निर्देश की वजह से x के प्रकार उम्मीद कर रहा था C::X हो सकता है, लेकिन इसके बजाय दोनों VS2010 और ऑनलाइन LLVM/बजना संकलक संकल्प X नाम स्थान B भीतर A::X होने के लिए। उपयोग घोषणा (using C::X) के साथ उपयोग निर्देश को बदलना, फिर यह C::X को अपेक्षित के रूप में हल करता है।

मानक निर्देशों का उपयोग करने पर कहते हैं [7.3.4.2]:

एक का उपयोग कर-निर्देश निर्दिष्ट करता है कि नामित नाम स्थान में नाम गुंजाइश है, जिसमें का उपयोग कर-निर्देशों का उपयोग करने के बाद प्रकट होता है में इस्तेमाल किया जा सकता -directive। अयोग्य नाम लुकअप (3.4.1) के दौरान, नाम प्रकट होते हैं जैसे उन्हें निकटतम संलग्न नामस्थान में घोषित किया गया था जिसमें उपयोग-निर्देश और मनोनीत नामस्थान दोनों शामिल हैं।

इस बात का मेरे पढ़ने के रूप में यदि नाम स्थान B भीतर घोषित, प्रभावी रूप से A::X छुपा कि C::X दिखाई देनी चाहिए है। निर्देशों का उपयोग करने और घोषणाओं का उपयोग करने के बीच मानक के कौन से खंड इस असंगतता के पीछे हैं? क्या किसी बाहरी दायरे से किसी निर्देश का उपयोग करके नाम छिपाने का कोई तरीका है?

+5

शायद सुराग * नामों में दिखाई देता है जैसे कि उन्हें निकटतम संलग्न नामस्थान में घोषित किया गया था जिसमें ** ** ** निर्देश-निर्देश और मनोनीत नामस्थान * दोनों शामिल हैं। क्या यह '::' नहीं होगा? और यदि ऐसा है, तो 'ए :: एक्स' पहले नहीं मिलेगा (लुकअप आंतरिक नामस्थान से बाहर जाता है) ... यकीन नहीं है, लेकिन जी ++ भी' ए :: एक्स' पिकअप करता है, इसलिए यह * बहुत * कंपाइलर्स में लगातार। –

+0

@ डेविड रोड्रिगुएज़ - ड्राईबीस: ओह, यह समझाएगा ... –

उत्तर

6

निर्देश के प्रयोग पर अध्याय हो रहा है किसी भी तरह स्पष्ट है कि आप की उम्मीद व्यवहार देख रहे हैं:

7.3.4p2 एक का उपयोग कर-निर्देश निर्दिष्ट करता है कि नामित नाम स्थान में नाम इस्तेमाल किया जा सकता उस दायरे में जिसमें उपयोग-निर्देश उपयोग-निर्देश के बाद प्रकट होता है। अयोग्य नाम लुकअप (3.4.1) के दौरान, नाम प्रकट होते हैं जैसे उन्हें निकटतम संलग्न नामस्थान में घोषित किया गया था जिसमें दोनों उपयोग-निर्देश और मनोनीत नामस्थान शामिल हैं।

7.3.4p3 एक उपयोग-निर्देश किसी भी सदस्य को घोषणात्मक क्षेत्र में नहीं जोड़ता है जिसमें यह प्रतीत होता है।

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

बाद में एक उदाहरण है कि कुछ और उदाहरण देकर स्पष्ट करने के लिए है है, लेकिन वास्तव में यह पता चलता है:

7.3.4p4 [...] एक और उदाहरण के लिए

namespace A { 
    int i; 
} 
namespace B { 
    int i; 
    int j; 
    namespace C { 
    namespace D { 
     using namespace A; 
     int j; 
     int k; 
     int a = i; // B::i hides A::i 
    } 

पिछले उदाहरण यही कारण है कि पारगमन को स्पष्ट करने के लिए प्रयोग किया जाता है (और इसमें अधिक कोड होता है), लेकिन अतिरिक्त कोड को हटाने के बाद यह वास्तव में आपके कोड के बराबर है।

तो ऐसा लगता है कि आपके मामले में का उपयोग कर निर्देश छुपा नहीं रहा है, बल्कि छुपाया जा रहा है।

+0

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

+0

मैं ऐसा कहूंगा। किसी भी दर पर, मैं * उपयोग-निर्देश * पूरी तरह से * से बचूंगा, और केवल * उपयोग-घोषणाओं * का उपयोग शायद ही कभी करूँगा। लुकअप बस इतना जटिल हो जाता है और यह निर्धारित करना कठिन होता है कि वास्तव में क्या उपयोग किया जा रहा है, जहां इसे परिभाषित किया गया है ... यदि आपकी आवश्यकता जटिल नेस्टेड नेमस्पेस के उपयोग को चपटा कर रही है, तो * नेमस्पेस उपनाम * पर विचार करें। –

+0

मैं अपने असली कोड में _using-directives_ से बचता हूं, यह नाम लुकअप नियमों का लाभ उठाकर 'कक्षा कहां रहता है' खोजने का एक प्रयास है। –