2016-07-25 6 views
5

मैं कुछ उदाहरण कोड देख रहा हूं जो एक ही कक्षा में कार्यों को कॉल करने के लिए this->functionname() और classname::functionname() दोनों का उपयोग करता है।सदस्य कार्यों को कॉल करने के लिए मुझे class- :: functionname() पर फ़ंक्शननाम() का उपयोग कब करना चाहिए?

क्या वास्तव में इन दो तरीकों के बीच एक अंतर है?

इसके अलावा, इन विधियों के बीच कोई अंतर है और केवल functionname() का उपयोग करके फ़ंक्शन को कॉल करना है?

धन्यवाद।

+0

इस सवाल का जवाब इस नए प्रलेखन thingy के लिए अच्छा उम्मीदवार है। – Dialecticus

उत्तर

4

सामान्य रूप से सी ++ में, चीज आपके विचार से कम सरल होती है।

सदस्य कार्यों को कॉल करने के तीन तरीके हैं। foo();

  • this साथ कॉल:

    1. सिर्फ फ़ंक्शन को कॉल this->foo();
    2. वर्ग के नाम का उपयोग करें: classname::f();

    नंबर # 1 और # 2 के बराबर हैं, कुछ लोगों को पसंद करते हैं क्योंकि # 2 यह स्पष्ट है कि यह एक सदस्य कार्य है और वैश्विक कार्य नहीं (ये लोग अल्पसंख्यक हैं)।

    चाहे # 3 और # 2 से भिन्न # 3 इस पर निर्भर करता है कि फ़ंक्शन कहा जाता है या नहीं, वर्चुअल फ़ंक्शन है। यदि यह गैर-वर्चुअल है तो इसमें कोई फर्क नहीं पड़ता है।यदि यह वर्चुअल और इस फ़ंक्शन का अधिक व्युत्पन्न ओवरराइड है तो # 1 और # 2 व्युत्पन्न फ़ंक्शन कहलाएगा और # 3 इस कक्षा में मौजूद ओवरराइड को कॉल करेगा (या यदि इस कक्षा में कोई ओवरराइड नहीं है , निकटतम सुपर-क्लास)।

    पिछले पैराग्राफ का अपवाद तब होता है जब कॉल-साइट कन्स्ट्रक्टर या विनाशक में होती है। इस मामले में, भले ही फ़ंक्शन वर्चुअल # 1 और # 2 # 3 जैसा ही व्यवहार करेगा (इसमें ओवरराइड को कॉल करें, या निकटतम सुपर-क्लास)।

    इसके अलावा यदि कार्य static है तो # 2 अमान्य है और # 1 और # 3 कक्षा के भीतर से बुलाए जाने पर बराबर हैं लेकिन वर्ग के बाहर से कॉल होने पर # 3 की आवश्यकता होती है।

    मुझे आशा है कि मैं कुछ भी :)

    बातें मैं याद किया याद नहीं किया: अगर समारोह एक वैश्विक रूप से छुपा है

    • this जरूरत हो सकती है बुला अंदर फिर से घोषित समारोह। @Dutow's answer देखें।
    • thistwo phase lookup (जब टेम्पलेट शामिल हैं) से निपटने के दौरान उपयोगी हो सकता है। उनकी टिप्पणी के लिए @Alejandro पर धन्यवाद।
    • मुझे लगता है कि using का उपयोग पानी में कुछ और मिट्टी फेंक सकता है लेकिन मुझे इस समय (चेतावनी emptor) में देखने के लिए परेशान नहीं किया जा सकता है।

    दरअसल, के रूप में सरल नहीं के रूप में एक सोच सकते हैं ...

  • +0

    आप तर्क भी दे सकते हैं कि 'यह' उचित [दो चरण लुकअप] के लिए भी आवश्यक है (http://blog.llvm.org/2009/12/dreaded-two-phase-name-lookup.html?m= 1) कुछ मामलों में – Alejandro

    +0

    @Alejandro, धन्यवाद, मैंने अपना जवाब अपडेट कर लिया है। – Motti

    3

    आमतौर पर? वह एक जैसे है। लेकिन संदर्भ के आधार पर, वे अलग-अलग चीजों का मतलब हो सकते हैं। जिसके परिणामस्वरूप,

    void f() { std::cout << "f" << std::endl; } 
    
    class Cl { 
    public: 
        void f() { std::cout << "Cl::f" << std::endl; } 
        void g() { 
         struct Cl { 
          static void f() { std::cout << "inside Cl::f" << std::endl; } 
         }; 
         void f(); 
    
         f(); 
         Cl::f(); 
         this->f(); 
        } 
    }; 
    
    int main() 
    { 
        Cl a; 
        a.g(); 
    
        return 0; 
    
    } 
    

    इस में, वैश्विक f छाया सदस्य विधि f की घोषणा:

    उदाहरण के लिए, निम्नलिखित चरम उदाहरण पर विचार (एक वास्तविक परियोजना में ऐसा नहीं करते हैं!) कार्यक्रम fCl::f के बजाय आउटपुट।

    स्थानीय struct Cl भी अपने स्वयं के टाइपनाम को छाया करता है, जिसके परिणामस्वरूप Cl::f() इसकी स्थिर f विधि को कॉल करता है।

    केवल this->f() पर कॉल करने से Cl::f पर कॉल करने में स्पष्ट रूप से परिणाम मिलते हैं।

    टाइपनाम का संस्करण आमतौर पर तब भी प्रयोग किया जाता है जब आप विरासत का उपयोग करते समय अभिभावक वर्ग में विधियों को कॉल करना चाहते हैं और आभासी तरीकों को ओवरराइड करते हैं - लेकिन यह तकनीकी रूप से समान वर्ग नहीं है।

    +0

    टीआईएल कि आप किसी फ़ंक्शन के अंदर फ़ंक्शन घोषित कर सकते हैं (और मैंने सोचा कि मेरा जवाब संपूर्ण था ...) – Motti

    +0

    और मैं 'Cl :: f' को ईंट करने में भी कामयाब रहा! :) – Dutow

    +0

    आप महोदय, बुराई हैं! ठीक है (मैंने आपके जवाब में मेरा जवाब दिया है)। – Motti

    1

    मुझे लगता है कि इसका उपयोग करने का एक कारण इस परिदृश्य में है। जैसे

    class A 
    { 
    public: 
        void foo() { this->doFoo(); } //equivalent to just doFoo(); 
        void foo2() { Abstract::doFoo(); } 
    private: 
        virtual void doFoo() { /* do stuff */ } 
    }; 
    

    स्निपेट में जब foo बुला यह सबसे व्युत्पन्न वर्ग में doFoo आह्वान करेंगे। foo2 पर कॉल करते समय यह हमेशा आधारभूत कार्यान्वयन को कॉल करेगा, भले ही यह ओवरराइड हो।

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