2012-06-12 22 views
6

मैं कोडप्रोजेक्ट पर डॉन क्लुगस्टन द्वारा article के माध्यम से जा रहा था। यह एक सुंदर लेख है और काफी प्रसिद्ध है।फंक्शन पॉइंटर्स

class A { 
public: 
     virtual int Afunc() { return 2; }; 
}; 

class B { 
public: 
     int Bfunc() { return 3; }; 
}; 

// C is a single inheritance class, derives only from A 
class C: public A { 
public: 
    int Cfunc() { return 4; }; 
}; 

// D uses multiple inheritance 
class D: public A, public B { 
public: 
    int Dfunc() { return 5; }; 
}; 

टुकड़ा निम्नलिखित पैराग्राफ द्वारा पीछा किया जाता:

मान लीजिए हम वर्ग सी में के लिए एक सदस्य समारोह सूचक बनाने के निम्नलिखित कोड का टुकड़ा में, मैं समझने के लिए एक विशेष धारणा बहुत मुश्किल पाया यह उदाहरण, अफुनक और सीएफएनसी दोनों सी के सदस्य कार्य हैं, इसलिए हमारे सदस्य फ़ंक्शन पॉइंटर को Afunc या Cfunc को इंगित करने की अनुमति है। लेकिन अफुनक को इस सूचक की आवश्यकता है जो सी :: ए (जिसे मैं एथिस कहूंगा), को इंगित करता है जबकि सीएफएनसी को इस पॉइंटर की आवश्यकता होती है जो सी को इंगित करती है (जिसे मैं सीथिस कहूंगा)। कंपाइलर लेखक इस स्थिति से एक चाल से निपटते हैं: वे सुनिश्चित करते हैं कि ए को सी की शुरूआत में शारीरिक रूप से संग्रहीत किया जाता है। इसका मतलब है कि एथिस == कैथिस। हमारे पास चिंता करने के लिए केवल एक ही है, और दुनिया के साथ अच्छी तरह से है।

एकमात्र चीज जिसे मैं समझना चाहता हूं वह उपरोक्त अनुच्छेद में बोल्ड और इटालिक्स में रेखा है।

मैं पूरी तरह से समझ में नहीं आता Afunc सेल्सियस के लिए एक सूचक की जरूरत :: जबकि एक Cfunc सी के लिए सूचक की जरूरत काफी स्वाभाविक है।

किसी भी मदद की सराहना की जाएगी।

उत्तर

9

सी ++ में सदस्य फ़ंक्शन को कॉल करके, आंतरिक रूप से ऐसा होता है कि उदाहरण एक छिपे हुए पहले तर्क के रूप में पारित किया गया है (ध्यान दें कि यह व्यवहार कड़ाई से क्रियान्वयन-परिभाषित व्यवहार है, हालांकि। C++ मानक के पास इस विषय पर कुछ भी कहना नहीं है , यह सिर्फ यह लागू करने की एक बहुत ही आम तरीका है):

x.f(y); // is treated internally as: 
f(&x, y); 

यह पहला तर्क तो this सूचक के माध्यम से उपलब्ध है।

अब, Afuncआंतरिक ऊपर के उदाहरण में, जबकि CFunc आंतरिक हस्ताक्षर void CFunc(C* const this) है हस्ताक्षर void Afunc(A* const this) है।

ध्यान दें कि दोनों मामलों में तर्क प्रकार अलग हैं, इसलिए जब आप एक ही ऑब्जेक्ट पर फ़ंक्शंस को कॉल करते हैं, तो एक अलग पॉइंटर पास होना होता है। सी ++ किसी भी व्युत्पन्न वस्तु से इसकी मूल वस्तु में एक अंतर्निहित रूपांतरण को परिभाषित करके हल करता है। यही कारण है, निम्नलिखित कोड में:

C* pc = something; 
pc->Afunc(); 

इस कोड को आंतरिक रूप से निम्नलिखित (छद्म कोड) के समान व्यवहार किया जाता है:

C* pc = something; 
Afunc(static_cast<A*>(pc)); 

यह डाली है, एकल विरासत के लिए, नहीं-आपरेशन (यानी इसे हटाया जा सकता है) उद्धरण में उल्लिखित चाल के माध्यम से: C ऑब्जेक्ट और उसके माता-पिता A ऑब्जेक्ट को उसी भौतिक पते पर संग्रहीत किया जाता है।प्रकार C की एक वस्तु जो स्मृति में कोई पता x में संग्रहीत किया जाता है शारीरिक रूप से इस तरह से कि प्रकार A की अपनी मूल वस्तु है भी पता x पर संग्रहीत में खर्च की गई थी, और C हो सकता है अन्य सभी सदस्यों द्वारा पीछा किया जाता (लेकिन आपके मामले में इसमें कोई सदस्य नहीं है, और sizeof(C) == sizeof(A))।

+0

क्या आप अंतिम वाक्य को फिर से लिख सकते हैं? – msiyer

+0

@msiyer मैंने अधिक जानकारी जोड़ने का प्रयास किया है, उम्मीद है कि यह थोड़ा स्पष्ट है। –

+0

यह एक महान स्पष्टीकरण है। मैं एक मैकेनिकल इंजीनियरिंग स्नातक हूं और इस प्रकार, किसी भी सीएस पाठ्यक्रम नहीं लिया है। मैं, अब, इसे अपने आप कर रहा हूँ। कंपाइलर डिज़ाइन और निर्माण में ठोस पैर रखने के लिए आवश्यक सभी को सीखना। इन तरह के उत्तरों के साथ, कोई वास्तव में सीएस औपचारिक शिक्षा को बहुत याद नहीं कर सकता है। धन्यवाद Konrad। – msiyer

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