2012-12-05 24 views
6
class Base1 
{ 
    private: 
    int testInput; 
    public: 
     Base1(); 
     virtual int GetRow(void) = 0; 
}; 

Base1::Base1() 
{ 
    testInput = 0; 
} 

class table : public Base1 
{ 
    private: 
    int row;  
    public: 
    table(); 
    virtual int GetRow(void); 
}; 

table::table() 
{ 
    //Contructor 
    row = 5; 
} 

int table::GetRow() 
{ 
    return row; 
} 

int main() 
{ 
    Base1* pBase = new table[3]; 
    pBase[0].GetRow(); 
    pBase[1].GetRow(); //when i get to this line, the compiler keep saying access 
          // violation. 
    pBase[2].GetRow(); 

    return 0; 
} 

मैं 3 टेबल क्लास की एक सरणी बनाने की कोशिश कर रहा हूं। आवश्यकता है कि मुझे ऐसा करने के लिए बेस ऑब्जेक्ट का उपयोग करना होगा।सी ++ में बहुरूपता के साथ सरणी कैसे बनाएं?

Base1 * pBase = new table[3]; 

मुझे ठीक लग रहा है। लेकिन जब मैंने प्रत्येक टेबल तक पहुंचने का प्रयास किया, तो कंपाइलर ने कहा कि यह उल्लंघन का उल्लंघन है। मुझे नहीं पता कि इस कोड के साथ क्या गलत है। हालांकि मैं विजुअल स्टूडियो 2010 का उपयोग कर रहा हूं।

उत्तर

13

सी ++ में, बहुलकता और सरणी मिश्रण नहीं करते हैं।

आम तौर पर व्युत्पन्न वर्ग का आकार आधार वर्ग के आकार से भिन्न होता है, बहुरूपता और सूचक अंकगणित अच्छी तरह से एक साथ नहीं खेलते हैं। चूंकि सरणी पहुंच में पॉइंटर अंकगणित शामिल है, pBase[1] जैसे अभिव्यक्ति अपेक्षित कार्य नहीं करते हैं।

एक संभावना है कि आपकी ऑब्जेक्ट्स में पॉइंटर्स की एक सरणी हो, शायद स्मृति प्रबंधन को सरल बनाने के लिए स्मार्ट पॉइंटर्स भी। लेकिन Base1 में आभासी विनाशक को परिभाषित करना न भूलें।

3

आप उन सभी सरणी तत्वों (new के साथ) बनाने की जरूरत है, इस तरह यह कार्य करें:

for(int i = 0; i < 3; ++i) 
    pBase[i] = new table(); 
6

आपको त्रुटि हो रही है क्योंकि सरणी स्थिर Base1 को लिखा गया।

pBase[1].GetRow(); 

pBase बाइट्स में Base1 के आकार कहते हैं और एक अन्य Base1 वस्तु की शुरुआत के रूप में इस व्याख्या है, लेकिन यह वास्तव में पहले table उदाहरण के बीच में किसी ऐसे स्थान पर बताते हैं: यह है कि इस लाइन का मतलब है।

यदि आपको पॉलिमॉर्फिक उदाहरणों की एक सरणी की आवश्यकता है, तो आपको पॉइंटर्स (या अधिमानतः कुछ स्मार्ट पॉइंटर्स) के माध्यम से उन्हें सरणी (या अधिमानतः std::vector में) में स्टोर करना होगा।

4

एग्नू की प्रतिक्रिया स्पॉट पर थी। मुझे थोड़ा और समझाने दो। अपने कोड बढ़ाने से, मैं एक Base1 के आकार और एक table वस्तु के साथ-साथ तीन table वस्तुओं के पतों का प्रिंट आउट के रूप में वे new ऑपरेटर द्वारा बनाई गई हैं:

A Base1 object is 8 bytes 
A table object is 12 bytes 
A table object is being constructed at 0x002977C0 
A table object is being constructed at 0x002977CC 
A table object is being constructed at 0x002977D8 

आप उन वस्तुओं रहे हैं देख सकते हैं स्मृति में एक दूसरे से अलग 12 बाइट्स दूरी।

pBase[0] is at 0x002977C0 
pBase[1] is at 0x002977C8 
pBase[2] is at 0x002977D0 

अब क्या होता है पर देखने: संकेत हम वापस पाने के 8 बाइट्स स्थान दिया गया है

अब, चलो पतों pBase [0], pBase [1] और pBase [2] देने का प्रिंट आउट करते हैं अलग। ऐसा इसलिए है क्योंकि पॉइंटर अंकगणित एक सूचक पर किया जाता है जिसका प्रकार Base1 है और Base1 8 बाइट लंबा है जो संकलक करता है pBase[n] को pBase + (n * sizeof(Base1)) में अनुवाद करना है।

अब आपको यह समझने में सक्षम होना चाहिए कि पहलेGetRow() काम करता है और आप दूसरे पर क्यों क्रैश करते हैं।

+0

और, shhh .. लेकिन सही प्रकार पर कास्टिंग, और फिर जाली प्रकार पर विधि को कॉल करने से क्रैश – johnathon

+0

का मतलब होगा आपका मतलब है ((तालिका) पीबीज़) [1] .GetRow() '? यह काम करेगा, लेकिन यह एक * भयानक * चीज है और लगभग निश्चित रूप से वापस आ जाएगी और आपको गधे में काट देगा। –

+0

हाँ मेरा मतलब बिल्कुल यही है। हां यह काफी 'भयानक' है, लेकिन यह सही पते पर पॉलीमोर्फिक वस्तुओं तक पहुंचने में कंपाइलर को संयोजित करने का एक वैध तरीका है। – johnathon

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