2013-03-22 8 views
8

मैं समझने के लिए सी ++ के साथ प्रयोग कर रहा हूं कि कक्षा/संरचनाओं और उनकी संबंधित वस्तुओं को स्मृति में कैसे रखा गया है और मुझे समझ में आया कि कक्षा/संरचना का प्रत्येक क्षेत्र उनके संबंधित ऑब्जेक्ट में ऑफसेट है (इसलिए मेरे पास एक सदस्य परिवर्तनीय सूचक हो सकता है)।किसी ऑब्जेक्ट के लिए सदस्य फ़ंक्शंस कहां संग्रहीत होते हैं?

मैं क्यों समझ में नहीं आता, मैं सदस्य समारोह संकेत हो सकता है, भले ही, निम्नलिखित कोड काम नहीं करता:

struct mystruct 
{ 
    void function() 
    { 
     cout << "hello world"; 
    } 
    int c; 
}; 

int main() 
{ 
    unsigned int offset_from_start_structure = (unsigned int)(&((mystruct*)0)->c); 
    unsigned int offset_from_start_structure2 = (unsigned int)(&((mystruct*)0)->function); // ERROR - error C2276: '&' : illegal operation on bound member function expression 



    return 0; 
} 

मेरा प्रश्न है: क्यों लाइन करता

unsigned int offset_from_start_structure = (unsigned int)(&((mystruct*)0)->c); 

संकलन और मुझे संरचना की शुरुआत से "सी" फ़ील्ड का ऑफसेट देता है और लाइन

unsigned int offset_from_start_structure2 = (unsigned int)(&((mystruct*)0)->function); 

डी संकलित भी नहीं है?

+5

सदस्य कार्य वस्तुओं में संग्रहित नहीं होते हैं (वे क्यों होंगे? वे उस प्रकार की सभी वस्तुओं के लिए समान हैं)। और अगर यह मदद करता है (शायद नहीं; शायद यह केवल भ्रम जोड़ता है लेकिन मैं वैसे भी कोशिश करूंगा) सदस्य फ़ंक्शन पॉइंटर्स * नहीं * पॉइंटर्स हैं। –

+0

क्या आप स्मृति में _function_ की सामग्री की अपेक्षा कर रहे थे? कार्य डेटा नहीं हैं। वे कोड हैं। –

+1

"मैं समझने के लिए सी ++ के साथ प्रयोग कर रहा हूं कि स्मृति/वर्ग और उनकी संबंधित वस्तुओं को स्मृति में कैसे रखा गया है" कार्यान्वयन विवरण, भाषा –

उत्तर

15

सदस्य कार्य या उन्हें संकेत वस्तु में संग्रहीत नहीं हैं। (virtual फ़ंक्शंस को आम तौर पर एक तालिका में संग्रहीत पॉइंटर के माध्यम से बुलाया जाता है जिस पर किसी ऑब्जेक्ट में एक पॉइंटर होता है) यह विशाल स्मृति की बर्बादी होगी। वे आम तौर पर कोड मेमोरी सेक्शन में संग्रहीत होते हैं, और कंपाइलर के लिए जाने जाते हैं। ऑब्जेक्ट (*this) आमतौर पर अदृश्य पैरामीटर के रूप में पारित किया जाता है ताकि कार्यों को पता चल सके कि किस ऑब्जेक्ट को कॉल करने के दौरान संचालित किया जाता है।

तो, आम आदमी के संदर्भ में, आप

0x10001000 void A::foo 
.......... {code for A::foo} 

और

push a; 
call A::foo (0x10001000) 
pop a; 

जहां a वस्तु आप पर foo कॉल कर रहे है होगा।

+0

आपकी स्पष्टीकरण के लिए धन्यवाद लेकिन लाइन क्यों काम नहीं करती है? इसे कम से कम –

+0

@ जॉनी पॉलिंग नंबर पर एक निश्चित पता वापस करना चाहिए, यह नहीं होना चाहिए। '& ((Mystruct *) 0) -> सी' अपरिभाषित व्यवहार है, आप केवल एक शून्य सूचक को अव्यवस्थित नहीं कर सकते हैं। 'सदस्य फ़ंक्शन के लिए सूचक' के लिए Google और आपको इसे करने का उचित तरीका मिल जाएगा। –

+0

मुझे नहीं लगता कि यह एक अनिर्धारित व्यवहार है, यह हर बार जब मैं इसे कॉल करता हूं तो सी क्षेत्र के ऑफसेट को लौटाता है और यह लगातार अन्य क्षेत्रों के लिए भी काम करता है, इसलिए मैं सोच रहा था कि यह फ़ंक्शन –

2

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

आप स्टैनले लिप्पमैन द्वारा “Inside the C++ object model” पकड़ने का प्रयास कर सकते हैं।

या, आप की पकड़ पाने के लिए कोशिश कर सकते हैं मेरे पुराने pointers tutorial, जो एक बार, विकिपीडिया के संकेत दिए गए लेख से संदर्भित किया गया था इससे पहले कि मेरे तो मुखपृष्ठ साइट गायब हो गया।


दूसरे प्रश्न के बारे में, क्यों p->memberFunc का पता लेने संकलक एक छोटे से गला घोंटना बनाता है, अच्छी तरह से है कि अभिव्यक्ति कोई प्रकार नहीं है, यह सिर्फ एक वाक्य इकाई, जो आप क्रम में करने के लिए एक तर्क सूची लागू कर सकते है समारोह को कॉल करने के लिए।

बुद्धि के लिए

,

struct S 
{ 
    void foo() {} 
}; 

#include <iostream> 
#include <typeinfo> 
using namespace std; 
int main() 
{ 
    S* p = 0; 
    typeid(&p->foo); 
} 

संकलन:

 
[W:\dev\test] 
>g++ foo.cpp 
foo.cpp: In function 'int main()': 
foo.cpp:12:17: error: ISO C++ forbids taking the address of a bound member function to form a pointer to member function. Say '&S::foo' [-fpermissive] 
foo.cpp:12:22: warning: value computed is not used [-Wunused-value] 
foo.cpp:12:22: warning: statement has no effect [-Wunused-value] 

[W:\dev\test] 
> _ 
संबंधित मुद्दे