2009-08-12 16 views
23

मैं निम्नलिखित कोड है, जो मूल रूप से किया गया था,क्या यह वैध सी ++ कोड है?

class foo { 
    public: 
    void method(); 
}; 

void foo::foo::method() { } 

मैंने गलती foo :: विधि की परिभाषा के सामने एक अतिरिक्त foo :: जोड़ा था था। यह कोड g ++ (ver 4.2.3) का उपयोग करके चेतावनी के बिना संकलित किया गया है, लेकिन विजुअल स्टूडियो 2005 का उपयोग करके बाहर निकला। मेरे पास नाम नाम का नाम नहीं था।

कौन सा संकलक सही है?

+0

बस सोच रहा है, लेकिन आप foo उपयोग कर रहे हैं और आपके वास्तविक कोड में विधि? या आप बस कुछ कोड को अलियासिंग कर रहे हैं जिसके साथ आप काम कर रहे थे? – jkeys

+1

मैंने उस कोड को एक फ़ाइल प्रोजेक्ट के रूप में कॉपी किया है और एक खाली मुख्य फ़ंक्शन जोड़ा है। यह वास्तव में जीसीसी 4.3.3 के तहत संकलित करता है। – Matt

+1

मैं पुष्टि कर सकता हूं कि यह वास्तव में किसी भी नामस्थान या किसी भी चीज़ के बिना चेतावनियों के बिना g ++ पर संकलित करता है (मैंने इसे 3.4.5 mingw पर आजमाया है)। दूसरी ओर एमएसवीसी 2008 ने इसे खारिज कर दिया। बहुत अजीब। –

उत्तर

25

यदि मैं मानक सही ढंग से पढ़ता हूं, तो g ++ सही है और वीएस गलत है।

आईएसओ आईईसी 14,882-2003 (ई), §9.2 वर्ग (pag.153): एक वर्ग-नाम गुंजाइश है, जिसमें इसे तुरंत घोषित किया जाता है के बाद वर्ग नाम में देखा जाता है में डाला जाता है। कक्षा का नाम कक्षा के दायरे में भी डाला जाता है; इसे इंजेक्शन-क्लास-नाम के रूप में जाना जाता है। पहुंच जांच के प्रयोजनों के लिए, इंजेक्शन-क्लास-नाम का इलाज इस तरह किया जाता है कि यह एक सार्वजनिक सदस्य नाम था।

आईएसओ आईईसी 14,882-2003 (ई), §3.4-3 नाम लुक (PAG:

नीचे टिप्पणी जारी रखते हुए, यह भी विशेष रूप से उपयोगी वास्तविक नाम लुक नियमों के विषय में निम्नलिखित बनाए रखने के लिए है। 2 9): नाम छिपाने और लुकअप के प्रयोजनों के लिए कक्षा (इंजेक्शन 9) का इंजेक्शन-क्लास-नाम भी उस वर्ग का सदस्य माना जाता है।

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

+1

दिलचस्प, क्या यह इस तथ्य को समझाता है कि foo :: foo :: foo :: विधि भी काम करती है? – MikeT

+2

पूरी तरह से नहीं, नहीं। इसके लिए मुझे लगता है कि वर्णन 3.4.3.1 पाया जा सकता है - योग्य नाम लुकअप: कक्षा या नामस्थान सदस्य का नाम :: स्कोप रिज़ॉल्यूशन ऑपरेटर (5.1) के बाद किसी नेस्टेड-नाम-विनिर्देशक पर लागू किया जा सकता है जो अपनी कक्षा या नामस्थान को नामांकित करता है। :: स्कोप रिज़ॉल्यूशन ऑपरेटर, ऑब्जेक्ट, फ़ंक्शन, और एन्यूमेरेटर नामों से पहले नाम के लिए लुकअप के दौरान अनदेखा किया जाता है। यदि नाम क्लास-नाम (क्लॉज 9) या नेमस्पेस-नाम (7.3.1) नहीं है, तो प्रोग्राम बीमार गठित –

+0

विशिष्ट नोट का है, "स्कोप रिज़ॉल्यूशन ऑपरेटर से पहले किसी नाम के लिए लुकअप के दौरान , ऑब्जेक्ट, फ़ंक्शन, और एन्युमरेटर नामों को अनदेखा किया जाता है। " –

0

क्या आपके पास शामिल किसी अन्य मॉड्यूल में नामस्थान फू है (और आप इसे केवल अनजान थे)? अन्यथा, यह सही नहीं है। मुझे यकीन नहीं है कि जी ++ ने इसकी अनुमति क्यों दी।

+0

दरअसल, जी ++ इसे अनुमति देता है। मैंने अभी परीक्षण किया। – Matt

+0

"मुझे यकीन नहीं है कि जी ++ ने इसकी अनुमति क्यों दी।" – jkeys

1

Comeau online बिना किसी हिचअप के इसे स्वीकार करता है, इसलिए यह लगभग दस वर्षों में कॉमो में मान्य या दूसरी बग है।

11

Krugar का सही उत्तर यहां है। यह नाम हर बार पाया जा रहा है इंजेक्शन क्लास नाम है। इंजेक्शन नाम के बिना

namespace NS 
{ 
    class B 
    { 
    // injected name B // #1 
    public: 
    void foo(); 
    }; 

    int i;    // #2 
} 

class B     // #3 
{ 
public: 
    void foo(); 
}; 


int i;     // #4 

class A :: NS::B 
{ 
public: 
    void bar() 
    { 
    ++i;   // Lookup for 'i' searches scope of 
        // 'A', then in base 'NS::B' and 
        // finally in '::'. Finds #4 

    B & b = *this; // Lookup for 'B' searches scope of 'A' 
        // then in base 'NS::B' and finds #1 
        // the injected name 'B'. 

    } 
}; 

वर्तमान देखने नियमों अंततः 'ए' की enclosing दायरे तक पहुंच जाएगा और:

निम्नलिखित एक उदाहरण है जो कम से कम एक कारण है कि संकलक इंजेक्शन वर्ग के नाम कहते हैं पता चलता है ':: बी' और 'एनएस :: बी' नहीं मिलेगा। इसलिए जब हम बेस क्लास को संदर्भित करना चाहते थे तो हमें ए में हर जगह "एनएस :: बी" का उपयोग करने की आवश्यकता होगी।

एक और जगह है कि इंजेक्शन के नाम आदत हो टेम्पलेट्स, जहां वर्ग टेम्पलेट के अंदर, इंजेक्शन नाम टेम्पलेट का नाम और प्रकार के बीच एक मैपिंग प्रदान करता है के साथ कर रहे हैं:

template <typename T> 
class A 
{ 
// First injected name 'A<T>' 
// Additional injected name 'A' maps to 'A<T>' 

public: 
    void foo() 
    { 
    // '::A' here is the template name 
    // 'A' is the type 'A<T>' 
    // 'A<T>' is also the type 'A<T>' 
    } 
}; 
संबंधित मुद्दे