प्रतिलिपि निर्माता में C ++ नेमस्पेस टकराव


33

मेरे पास निम्नलिखित कोड हैं:

namespace A {
    struct Foo {
        int a;
    };
}

struct Foo {
    int b;
};

struct Bar : public A::Foo {
    Bar(Foo foo) {
        c = foo.b;
    }
    int c;
};

C ++ कंपाइलर "c = foo.b" पर शिकायत करता है क्योंकि A :: Foo में b नाम का कोई सदस्य नहीं है। अगर मैं बार पैरामीटर के प्रकार के साथ :: Foo यह काम करता है।

मेरा सवाल यह है कि इस व्यवहार के पीछे क्या तर्क है (मुझे लगता है कि इस तथ्य के साथ यह करना है कि विरासत बनाता है बार एक नामस्थान में प्रवेश करता है, लेकिन मुझे इस सिद्धांत का समर्थन करने के लिए कोई दस्तावेज नहीं मिल सकता है।


8
मुझे लगता है कि यह तर्क पर निर्भर देखने से संबंधित है। मैंने "भाषा-वकील" को टैग किया है क्योंकि मुझे लगता है कि आप भाषा मानक के संदर्भ में उत्तर देने के बाद हैं। और एक बहुत अच्छा पहला सवाल! इसे सभी सार्थक बनाता है।
बाथशीबा

यह नामस्थान में प्रवेश नहीं करता है A, जिसे आप देख सकते हैं कि क्या आप Barकिसी अन्य संरचना से इनहेरिट करते हैं A। फिर कोई अस्पष्टता नहीं है। यह और अधिक है जैसे कि इनहेरिटेंस के संकल्प A::Fooको Barशामिल करने से लेकर सब कुछ जोड़ता Fooहै A::Foo। क्षमा करें, मैं वास्तव में इसे अधिक सटीक व्यक्त नहीं कर सकता।
n314159

@Bathsheba क्या आप का मतलब है तर्क प्रकार आश्रित नाम देखने के लिए फ़ंक्शन नाम (या फ़ंक्शन टेम्पलेट नाम) या टेम्पलेट में निर्भर नाम खोजने के लिए?
जिज्ञासु

जवाबों:


22

हर वर्ग के सदस्य के रूप में इसका नाम इसमें शामिल है। तो आप नाम दे सकते हैं A::Foo::Foo। इसे इंजेक्टेड क्लास नेम कहा जाता है।

[कक्षा]

2 एक वर्ग-नाम उस दायरे में डाला जाता है जिसमें वर्ग-नाम दिखाई देने के तुरंत बाद घोषित किया जाता है। वर्ग-नाम भी वर्ग के दायरे में डाला गया है; इसे इंजेक्शन-क्लास-नाम के रूप में जाना जाता है। पहुँच जाँच के प्रयोजनों के लिए, इंजेक्शन-वर्ग-नाम को ऐसे माना जाता है जैसे कि वह एक सार्वजनिक सदस्य नाम हो।

[Basic.lookup]

3 नाम छिपाने और देखने के प्रयोजनों के लिए एक वर्ग के इंजेक्शन-वर्ग-नाम को भी उस वर्ग का सदस्य माना जाता है।

क्योंकि तर्क प्रकार का अयोग्य नाम लुकअप वर्ग के दायरे में शुरू होता है Bar, इसलिए यह किसी भी सदस्य के लिए अपने आधार वर्ग के दायरे में जारी रहेगा। और यह A::Foo::Fooएक प्रकार के नाम के रूप में मिलेगा ।

यदि आप वैश्विक प्रकार के नाम का उपयोग करना चाहते हैं, तो बस इसके आसपास (वैश्विक) नामस्थान द्वारा इसे अर्हता प्राप्त करें।

Bar(::Foo foo) {
    c = foo.b;
}

जो एक ऐसे दायरे में पूरी तरह से योग्य खोज कर रहा है जहां इंजेक्शन वर्ग का नाम दिखाई नहीं देता है।

एक फॉलोअप के लिए "क्यों" प्रश्न देखें


5
@TedLyngmo - ADL फ़ंक्शन कॉल के साथ होता है, उन विशिष्ट मार्ग में प्रासंगिक कुछ भी नहीं है।
स्टोरीटेलर - Unslander मोनिका

ओकी, मैं पढ़ रहा था और निश्चित नहीं था। धन्यवाद!
टेड लिंगमो

3
यह बहुत मनोरंजक होता है, struct Bar:: A::Foo::Foo::Foo::Foo::Foo {}; लेकिन ऐसे संदर्भ हैं जहां A::Foo::Fooकंस्ट्रक्टर को नामित किया जाता है और इस प्रकार आप जितने चाहें Fooउतने जोड़ना जारी नहीं रख सकते हैं। यह इस तथ्य के समान (लेकिन पूरी तरह से अलग तंत्र के साथ) है कि आप एक फ़ंक्शन को fइस तरह से कॉल कर सकते हैं (************f)():।
एपीग्रामग्राम

@AProgrammer - वास्तव में। और एक और भी मनोरंजक उदाहरणों का निर्माण कर सकता है ।
स्टोरीटेलर - अनसलैंडर मोनिका

यह उत्तर निश्चित रूप से "क्या" बताता है। क्या "क्यों" को जोड़ने के लिए इसमें सुधार किया जा सकता है? जैसे, इस नियम का उद्देश्य क्या है? कौन से उपयोग के मामलों में सुधार होता है या संभव है?
davidbak

2

पूर्ण उत्तर नहीं, केवल कोड जो दिखाता है (चूंकि यह संकलन करता है) जो Barप्रवेश नहीं करता है namespace A। आप देख सकते हैं कि जब वंशानुक्रम A::Foo1में कोई समस्या नहीं है, तो अस्पष्टता के साथ कोई समस्या नहीं Fooहोगी यदि यह विरासत Barप्रवेश करने देती है तो यह अलग होगा A

namespace A {
    struct Foo {
        int a;
    };

    struct Foo1 {
        int a;
    };
}

struct Foo {
    int b;
};

struct Bar : public A::Foo1 {
    Bar(Foo foo) {
        c = foo.b;
    }
    int c;
};
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.