2012-01-28 45 views
10
void foo(int) 
{ 
} 

class X 
{ 
    void foo() 
    { 
    } 

    void bar() 
    { 
     foo(42); 
     // error: no matching function for call to 'X::foo(int)' 
     // note: candidate is: 
     // note: void X::foo() 
     // note: candidate expects 0 arguments, 1 provided   
    } 
}; 

सी ++ मुक्त फ़ंक्शन को कॉल करने में असमर्थ क्यों है (जो सही हस्ताक्षर वाला एकमात्र है)?सदस्य फ़ंक्शन छुपाएं फ़ंक्शन

+2

इस मामले में, आप बाहरी foo तक पहुंचने के लिए ':: foo (42)' का उपयोग कर सकते हैं। [आइडिया डेमो] (http://ideone.com/6HljO)। लेकिन मुझे नामस्थानों के बारे में बहुत कुछ पता नहीं है। –

+0

मैं इसे सी ++ की एक एचिलीस एड़ी मानता हूं। यह सामान्य अधिभारित मुक्त फ़ंक्शन नामों का असाधारण उपयोग करता है, जैसे कि इस्प्टी (चीज), जहां चीजों को दिए गए सामानों के लिए कई अधिभार हैं, जबकि चीज़ को अनुमति देना। (छूट) भी मौजूद है। बेवकूफ, दुर्भाग्यपूर्ण, गुंजाइश। – Mordachai

उत्तर

5

तार्किक कारण संगति है:

अपने उदाहरण में वैश्विक फ़ंक्शन को कॉल करने के लिए, :: सिंटैक्स का उपयोग करें।

    सुझाव के अनुसार
  • मान लीजिए, संकलक ::foo(int) को foo(42) हल करता है।
  • अब कुछ समय बाद, यदि आप X::foo() से X::foo(int) बदलते हैं तो foo(42) को X::foo(int) पर हल किया जाएगा। जो संगत नहीं है।

यही कारण है कि समान नाम होने पर व्युत्पन्न वर्ग कार्य बेस क्लास फ़ंक्शन छुपाता है।

ऐसे मामलों को 2 तरीकों से हल किया जा सकता है;

(1) पूरी तरह से योग्य नाम दें (उदा ::foo(42))

(2) using उपयोगिता का उपयोग करें; जैसे

void bar() 
{ 
    using ::foo; 
    foo(42); 
} 
+1

अगर कोई बाद में foo (int) सदस्य जोड़ता है, तो वे स्पष्ट रूप से इसका इरादा रखते हैं। खराब भाषा डिजाइन, आईएमओ। – Mordachai

12

क्योंकि दो पहचानकर्ताओं को विभिन्न क्षेत्रों में परिभाषित किया गया है, और ओवरलोड रिज़ॉल्यूशन केवल उसी दायरे में कार्यों के बारे में चिंतित है। एक बार संकलक को पता चलता है कि कक्षा में foo है, यह व्यापक स्कॉप्स (सी ++ 11 §3.4.1/1) पर चढ़ना बंद कर देता है, इसलिए नि: शुल्क फ़ंक्शन foo छिपा हुआ है। - मैं नहीं जानता कि भाषा कल्पना में है कि पीछे तर्क था क्या

::foo(42); 
+1

नोट: यह 'int' की वजह से एक विशिष्ट मामला है, अधिकांश बार यह अभी भी काम करता है क्योंकि एडीएल अच्छा है। –

0

मैं क्यों अपने प्रश्न का हिस्सा उत्तर नहीं दे सकता:

आप वैश्विक foo का उल्लेख करने के लिए एक योग्य नाम का उपयोग करने की आवश्यकता है ।

::foo(42); 
0

इस का कारण यह तथ्य यह है कि संकलक एक मिलान समारोह नाम के लिए प्रथम दिखेगा, वापसी मूल्यों और मानकों की अनदेखी कर रहा है। एक कक्षा के अंदर, यह वहां एक मिलते-जुलते सदस्य की तलाश करने की कोशिश करेगा (वास्तव में, यह "ऊपर" जाने वाले सभी क्षेत्रों को देखेगा; स्थानीय दायरे, फ़ंक्शन स्कोप, क्लास स्कोप, नेमस्पेस स्कोप, ग्लोबल स्कोप इत्यादि।)।

X::foo पहला मिलान नाम है। फिर (पहले नहीं) यह पैरामीटर के आधार पर सही अधिभार (यदि कई घोषणाएं हैं) चुनने का प्रयास करेंगे (यही कारण है कि आप एक ही फ़ंक्शन को विभिन्न पैरामीटर के साथ अधिभारित कर सकते हैं लेकिन केवल अलग-अलग रिटर्न मान नहीं) और फिर यह जांच करेगा वापसी मूल्य (यदि कोई है तो)।

1

वास्तव में आपके प्रश्न की तरह।इसके अलावा, मैं इस वाक्य विन्यास का उपयोग कह सकते हैं,:

::foo(42); 

लेकिन मैं कह सकता हूँ कि मेरी राय में यह और अधिक सुरुचिपूर्ण और अच्छा प्रोग्रामिंग, सेट नामस्थान है, तो आप कुछ इस तरह लिख सकते हैं:

namespace MyNameSpace 
{ 
    void foo(int){} 

    class X 
    { 
     void foo(){} 

     void bar() 
     { 
      MyNameSpace::foo(42); 
     } 
    }; 
}; 

यह एक अच्छी बात है क्योंकि Namespaces नाम के तहत कक्षाओं, वस्तुओं और कार्यों को समूहित करने की अनुमति देता है।

पीएस: फिर यह आपके पास कोई नामस्थान नहीं होने पर ::foo(42); लिखने के अर्थ को समझने में आपकी सहायता करता है।

2

बाहरी क्षेत्र में एक नाम बाहरी क्षेत्रों में नाम छुपाता है। इससे कोई फर्क नहीं पड़ता कि यह एक समारोह है या कुछ और, या यदि आप कक्षा या नामस्थान में हैं।

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

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