2011-08-26 11 views
6

क्षमा करें।सरणी वस्तुओं जटिल खिताब के लिए

class Base 
{ 
public: 
    int SomeMember; 
    Base() : SomeMember(42) {} 
    virtual int Get() { return SomeMember; } 
}; 

class ChildA : public Base 
{ 
public: 
    virtual int Get() { return SomeMember*2; } 
}; 

class ChildB : public Base 
{ 
public: 
    virtual int Get() { return SomeMember/2; } 
}; 

class ChildC : public Base 
{ 
public: 
    virtual int Get() { return SomeMember+2; } 
}; 

Base ar[] = { ChildA(), ChildB(), ChildC() }; 

for (int i=0; i<sizeof(ar)/sizeof(Base); i++) 
{ 
    Base* ptr = &ar[i]; 
    printf("El %i: %i\n", i, ptr->Get()); 
} 

कौन सा आउटपुट:

El 0: 42 
El 1: 42 
El 2: 42 

यह सही व्यवहार है (वीसी ++ 2005 में) मैं कुछ इस तरह है? पूरी तरह से ईमानदार होने के लिए, मुझे उम्मीद है कि इस कोड को संकलित नहीं किया जाए, लेकिन ऐसा हुआ, हालांकि यह मुझे आवश्यक परिणाम नहीं देता है। क्या ये संभव भी है?

उत्तर

8

हाँ, यह सही व्यवहार है। कारण

Base ar[] = { ChildA(), ChildB(), ChildC() }; 

class Base की वस्तुओं पर तीन अलग-अलग वर्गों की वस्तुओं को कॉपी करके सरणी तत्वों initializes और कि class Base की वस्तुओं की पैदावार और इसलिए आप सरणी के प्रत्येक तत्व से class Base के व्यवहार का पालन है।

आप विभिन्न वर्गों आप उन्हें उनके लिए new और दुकान संकेत के साथ आवंटित करने की वस्तुओं संग्रहीत करना चाहते हैं।

+5

* ऑब्जेक्ट टुकड़ा करने की क्रिया *, के रूप में यह जाना जाता है। – john

+0

तो यह अपने VTables कॉपी किए बिना ऑब्जेक्ट्स की प्रतिलिपि बना रहा है? – GhassanPL

+0

@ क्रोनिकारज़: यह उन पर अन्य वर्गों की सामग्री की प्रतिलिपि बनाकर 'कक्षा व्युत्पन्न' की वस्तुओं को आरंभ करता है। बेशक यह vtables की प्रतिलिपि नहीं है - वे अपरिवर्तनीय हैं। – sharptooth

2

बहुरूपी आपके द्वारा अपेक्षित व्यवहार, आप Base की ओर इशारा की सरणी का उपयोग करें और new के माध्यम से वस्तुओं को बनाने चाहिए प्राप्त करने के लिए:

Base* ar[] = { new ChildA(), new ChildB(), new ChildC() }; 
+2

आप स्मृति, बुरे लड़के को लीक कर रहे हैं। –

0

क्या वास्तव में हो रहा है कि:

  1. के प्रकार के बाद से ar [] आधार है, 3 * आकार (आधार) स्मृति की मात्रा आर को आवंटित की जाती है।

  2. चूंकि आपने बेस के लिए एक स्पष्ट प्रतिलिपि निर्माता घोषित नहीं किया है, इसलिए आधार की डिफ़ॉल्ट प्रतिलिपि निर्माता को बुलाया जाता है जिसे केवल चाइल्डए, चाइल्डबी और चाइल्डसी ऑब्जेक्ट्स के "बेस" भाग को सरणी ar में निहित बेस ऑब्जेक्ट्स में कॉपी किया जाता है (डिफ़ॉल्ट प्रतिलिपि कन्स्ट्रक्टर पर्याप्त बुद्धिमान है कि बिट वर्चुअल पॉइंटर में चाइल्ड ऑब्जेक्ट्स के वर्चुअल पॉइंटर को कॉपी करने की आवश्यकता नहीं है)।

  3. ar [0], ए आर [1] और ए आर [2] की आभासी संकेत बेस इंगित :: हो जाओ तो बेस :: हो जाओ कहा जाता है।

यहां मुद्दा यह ध्यान रखें कि जो एक वस्तु इंगित करेगा की आभासी सूचक हमेशा निष्पादन से पहले जाना जाता है के लिए कार्य है।

इस मामले में, रनटाइम पहले से जानता था कि सरणी में "बेस" ऑब्जेक्ट होते हैं, इसलिए यह अपने Vptr को सेट करता है ताकि बेस :: को इंगित किया जा सके जैसे ही उन्हें स्मृति आवंटित किया गया हो।

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