2012-02-26 9 views
6

निम्नलिखित कोड जीसीसी में संकलन नहीं करता है:C++ और इंजेक्शन आधार नाम

namespace One{ 
    class A{ 
    }; 
}; 

namespace Two{ 
    class A{ 
     public: 
     void what(){ 
      cout << "Two::A says what!" << endl; 
     } 
    }; 

    class B : public One::A{ 
     public: 
     B(){ 
      A xx; 
      xx.what(); 
     } 
    }; 

}; 

और यह देता है:

gccbug.cpp: In constructor ‘Two::B::B()’: 
gccbug.cpp:23: error: ‘class One::A’ has no member named ‘what’ 

अब, मुझे बताया गया था कि यह सही व्यवहार (इंजेक्शन आधार की वजह से है वन :: ए बनाने का नाम ए :: ए का संदर्भ लें। हालांकि, यह कोड सी # में संकलित है (ठीक है, कुछ चीजों को बदलने के बाद), इसलिए यह सी ++ विशिष्ट प्रतीत होता है।

मैं क्या सोच रहा हूं .. क्यों? क्या आधार नाम "वन :: ए" को "ए" के रूप में इंजेक्शन देने का कोई विशिष्ट उद्देश्य है?

+6

बस संदर्भ के लिए, सी #! = सी ++। मुझे यकीन नहीं है कि आप दो –

+0

की तुलना क्यों कर रहे हैं, मैं निश्चित रूप से नहीं कह सकता (मेरे पास अभी मेरी प्रतिलिपि नहीं है), लेकिन एक तरफ के रूप में, सी ++ भाषा को इस तरह से डिजाइन क्यों किया गया था इसके बारे में प्रश्न स्ट्रॉस्ट्रप द्वारा "द डिज़ाइन एंड इवोल्यूशन ऑफ सी ++" नामक पुस्तक में अक्सर उत्तर दिया जाता था। –

+0

@ टोनी थेलियन, ठीक है, यह दूसरी सी-जैसी प्रोग्रामिंग भाषा है जिसमें "नेमस्पेस" है, और एक जिसे मैंने एक कंपाइलर तक पहुंचाया था। मैं यह नहीं कह रहा हूं कि केवल "एक सच्चा तरीका" है जिसमें यह सही है, लेकिन यह कम से कम इस उदाहरण को देखते हुए अंतर्ज्ञानी प्रतीत नहीं हुआ। – kamziro

उत्तर

3

एकमात्र कारण मैं के बारे में सोच सकते हैं कि C++ आप इस तरह निर्माता के प्रारंभकर्ता सूची में आधार वर्ग नाम का उल्लेख करने, संभावना है आपके उदाहरण में से एक, क्योंकि आप वास्तव में कन्स्ट्रक्टर के अंदर एक स्थानीय चर घोषित करते हैं, जबकि मेरे उदाहरण में, A()A के प्रकार को संदर्भित करता है जो विरासत के कारण class B की परिभाषा में निहित है।

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

+0

आह, हाँ, यह वास्तव में समझ में आता है। हालांकि मैं कहता हूं कि यह "हैक" जैसा थोड़ा सा लगता है। – kamziro

3

क्या आधार नाम "वन :: ए" को "ए" के रूप में इंजेक्शन देने का कोई विशिष्ट उद्देश्य है?

हां। यह है ताकि आप इस लिख सकते हैं:

namespace N 
{ 
    class A 
    { 
     A *a; 
    }; 
} 

अभाव इंजेक्शन-नाम की में, आप N::A *a लिखने के लिए है जो अच्छा नहीं है।

ध्यान दें कि यह इंजेक्शन-नाम की वजह से है, निम्नलिखित लाइनों अनुमति दी जाती है:

A::A *a1; //ok 
A::A::A *a2; //ok 
A::A::A::A *a3; //ok 
A::A::A::A::A *a4; //ok 
//and so on 

Online demo

+0

क्या यह पूछताछकर्ता द्वारा समझाया गया परिस्थिति से अलग नहीं है?मूल उदाहरण में 'कक्षा बी' एक नामस्थान के अंदर था, लेकिन जिस वर्ग से यह निकाला गया वह दूसरे में था। – jogojapan

+1

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

+0

@ बो पर्सन हां। मैं बस यह इंगित कर रहा हूं कि उपर्युक्त उदाहरण इस बिंदु को बिल्कुल स्पष्ट नहीं करता है। उपर्युक्त उदाहरण में 'कक्षा ए' का एकमात्र संदर्भ उसी नामस्थान के अंदर ही कक्षा की घोषणा के रूप में है। इसके लिए आपको नाम इंजेक्शन की आवश्यकता नहीं है। – jogojapan

0

One:: साथ A योग्यता करके आप namespace एक दायरे में से A जोड़ा है, इसलिए संकलक इसके नाम संकल्प के लिए वहां देखेंगे।

namespace Two { 

    /*...*/ 

    class B : public One::A { 
    public: 
    B():A() 
    { 
     /*...*/ 
    } 
    }; 
} 

बेशक उद्देश्य तो अलग है:

+0

लेकिन निर्माता के अंदर घोषित 'ए' प्रकार की वस्तु' एक :: 'के साथ योग्य नहीं है। इसका अर्थ 'नेमस्पेस वन' से संबंधित है, हालांकि 'कक्षा बी' की घोषणा वास्तव में 'नामस्थान दो' के अंदर है। – jogojapan

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