2011-08-25 6 views
97

मैं आज नौकरी साक्षात्कार में गया और यह दिलचस्प सवाल दिया गया।व्युत्पन्न वस्तुओं की एक सरणी के आधार बिंदु के लिए एक सूचक?

स्मृति रिसाव के अलावा और तथ्य यह नहीं है कि कोई वर्चुअल डॉटर नहीं है, यह कोड क्रैश क्यों होता है?

#include <iostream> 

//besides the obvious mem leak, why does this code crash? 

class Shape 
{ 
public: 
    virtual void draw() const = 0; 
}; 

class Circle : public Shape 
{ 
public: 
    virtual void draw() const { } 

    int radius; 
}; 

class Rectangle : public Shape 
{ 
public: 
    virtual void draw() const { } 

    int height; 
    int width; 
}; 

int main() 
{ 
    Shape * shapes = new Rectangle[10]; 
    for (int i = 0; i < 10; ++i) 
     shapes[i].draw(); 
} 
+1

गायब अर्धविराम के अलावा, आपका मतलब है? (यह संकलन-समय त्रुटि होगी, हालांकि, रनटाइम नहीं) –

+0

क्या आप वाकई सभी वर्चुअल थे? –

+0

@ योचई, हाँ मुझे यकीन है। –

उत्तर

148

आप इस तरह इंडेक्स नहीं कर सकते। आपने Rectangles की एक सरणी आवंटित की है और shapes में पहले पॉइंटर संग्रहीत किया है। जब आप shapes[1] करते हैं तो आप (shapes + 1) को संदर्भित कर रहे हैं। यह आपको अगले Rectangle पर पॉइंटर नहीं देगा, लेकिन Shape की अनुमानित सरणी में अगले Shape के लिए एक सूचक होगा। बेशक, यह अपरिभाषित व्यवहार है। आपके मामले में, आप भाग्यशाली और दुर्घटनाग्रस्त हो रहे हैं।

Rectangle पर पॉइंटर का उपयोग करके इंडेक्सिंग सही तरीके से काम करता है।

int main() 
{ 
    Rectangle * shapes = new Rectangle[10]; 
    for (int i = 0; i < 10; ++i) shapes[i].draw(); 
} 

आप सरणी में Shape रों के विभिन्न प्रकार के हैं और उन्हें उपयोग करना चाहते हैं polymorphically आप आकृति को संकेत की एक सरणी की जरूरत है।

+0

हाँ यह सही है। :) –

13

पॉइंटर को अनुक्रमणित करते समय, कंपाइलर सरणी के अंदर स्थित चीज़ों के आकार के आधार पर उपयुक्त राशि जोड़ देगा। तो कहें कि आकार (आकार) = 4 (क्योंकि इसमें कोई सदस्य चर नहीं है)। लेकिन आकार (आयताकार) = 12 (सटीक संख्याएं गलत हैं)।

तो जब आप पहले तत्व के लिए 0x0 कहने लगते हैं, तो जब आप 10 वें तत्व तक पहुंचने का प्रयास करते हैं तो आप किसी अमान्य पते या उस स्थान पर जाने का प्रयास कर रहे हैं जो ऑब्जेक्ट की शुरुआत नहीं है।

+1

एक गैर सी ++ के रूप में, आकारऑफ() के उल्लेख से मुझे समझने में मदद मिली कि @ आर। मार्टिनो अपने जवाब में कह रहे थे। –

36

जैसा कि मार्टिनो फर्नांडीस ने कहा, अनुक्रमण गलत है। यदि आप आकार की एक सरणी स्टोर करने के लिए के बजाय चाहता था, आप तो जैसे आकार * के की एक सरणी का उपयोग कर ऐसा करने के लिए, होगा:

int main() 
{ 
    Shape ** shapes = new Shape*[10]; 
    for (int i = 0; i < 10; ++i) shapes[i] = new Rectangle; 
    for (int i = 0; i < 10; ++i) shapes[i]->draw(); 
} 

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

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