2012-10-24 16 views
9

से भर उन आभासी लागू किया तरीकों के साथ अगर मैं एक आधार वर्ग, केवल आभासी तरीकों और आधार वर्ग से 2 व्युत्पन्न वर्ग के साथ की है।सूचक,, व्युत्पन्न वर्ग

मैं कैसे करूँ:

// causes C2259 
BaseClass* base = new BaseClass[2]; 

BaseClass[0] = new FirstDerivedClass; 
BaseClass[1] = new SecondDerivedClass; 

या:

// causes "base is being used without being initialized" 
BaseClass* base; 
// causes CC59 again 
BaseClass* base = new BaseClass; 

base[0] = FirstDerivedClass(); 
base[1] = SecondDerivedClass(); 

(या कुछ इसी तरह)

... ताकि मैं DerivedClass के माध्यम से BaseClass रों तरीकों का उपयोग कर सकते, लेकिन सूचक और सूचक द्वारा DerivedClass एस की एक सरणी है?

उत्तर

8

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

भले ही BaseClass अमूर्त नहीं थे, सरणी का उपयोग करके बहुलक रूप से big no-no सी ++ में है ताकि आपको किसी भी मामले में चीजों को अलग-अलग करना चाहिए।

करने के लिए कोड को बदलकर इस फिक्स:

BaseClass** base = new BaseClass*[2]; 

BaseClass[0] = new FirstDerivedClass; 
BaseClass[1] = new SecondDerivedClass; 

जिसके अनुसार, ज्यादातर समय यह गूंगा संकेत के बजाय सादे सरणियों और स्मार्ट संकेत (जैसे std::shared_ptr के रूप में) के बजाय std::vector उपयोग करने के लिए बेहतर है। मैन्युअल रूप से कोड लिखने के बजाय इन उपकरणों का उपयोग करना बहुत ही कम रनटाइम लागत पर पारदर्शी रूप से कई मुद्दों का ख्याल रखेगा।

+1

समस्या, जिसे "ऑब्जेक्ट स्लाइसिंग" कहा जाता है, सरणी के लिए विशिष्ट नहीं है - यह तब भी होता है जब आप किसी व्युत्पन्न क्लास को बेस क्लास * मान * द्वारा असाइन करते हैं। जैसे 'बेस क्लास बी; बी = फर्स्टडेरिव क्लास(); 'संकलित सी ++ है जो फिर भी चुपचाप तोड़ता है (सबसे अच्छा आपको एक कंपाइलर चेतावनी मिल सकती है)। –

+0

लिंक को स्थानांतरित किया जाना प्रतीत होता है। – user6003859

+1

@ user6003859 मैंने इसे अपडेट किया, स्पॉटिंग के लिए धन्यवाद! – Jon

3

यह सी ++ सरल सरणी के बजाय std::vector उपयोग करते हैं:

std::vector<BaseClass*> base; 
base.push_back(new FirstDerivedClass()); 
base.push_back(new SecondDerivedClass()); 

Kerrek SB के रूप में देखा सबसे सुरक्षित विधि का उपयोग करने के लिए है std::unique_ptr:

std::vector<std::unique_ptr<BaseClass> > base; 
base.push_back(std_unique_ptr<BaseClass>(new FirstDerivedClass())); 
base.push_back(std_unique_ptr<BaseClass>(new SecondDerivedClass())); 
+2

लेकिन अगर मुझे कोई सरणी चाहिए? – Deukalion

+1

के लिए क्या? स्पीड? विश्वसनीयता? –

+0

इसके बारे में क्या: बेस क्लास * बेस [2]; बेस [0] = नया फर्स्टडेर क्लास; बेस [1] = नया सेकेंडडिएड क्लास; – Al2O3

2

अपने BaseClass शुद्ध आभासी तरीकों हो, तो यह संकलन करने असफल हो जायेगी:

BaseClass* base = new BaseClass[2]; 

यह नहीं, तो आप स्मृति रिसाव पाने के लिए जा रहे हैं करता है।

C++ में, यह, std :: वेक्टर या std :: सारणी का उपयोग करके स्मार्ट सूचक किसी तरह का साथ किया जाता है। उदाहरण के लिए:

std::vector< std::shared_ptr<BaseClass> > arr(2); 
arr[0].reset(new FirstDerivedClass()); 
arr[1].reset(new SecondDerivedClass()); 
+0

ओपी के कोड के साथ एक और भी महत्वपूर्ण समस्या * ऑब्जेक्ट स्लाइसिंग * है, जो चुपचाप प्रोग्राम को तोड़ देती है। –

+0

@j_random_hacker यही कारण है कि मैंने किसी प्रकार का स्मार्ट सूचक उपयोग करने का सुझाव दिया। बेस प्रकार की वस्तुओं को संग्रहीत करना (यदि इसमें कोई शुद्ध कार्य नहीं है) –

0

यह (Rubby से)

BaseClass* Base[2]; 

Base[0] = new FirstDerivedClass; 
Base[1] = new SecondDerivedClass; 
+1

स्लाइसिंग का कारण बनता है यह आपके मूल कोड को करने का प्रयास करने से कुछ * बहुत * अलग है। यह सरणी ढेर पर आवंटित की जाती है, जबकि मूल रूप से यह ढेर पर था। – Jon

+0

हाँ, मुझे लगता है। अब सरणी एक सूचक है और सरणी में पॉइंटर्स हैं। – Deukalion

0

जवाब था एक सूचक सरणी को परिभाषित करें, सूचक प्रकार BaseClass है। और सरणी के तत्वों को डेरिवक्लास को पॉइंटर असाइन करें। जैसे:

BaseClass* base [2]; 
base[0] = new FirstDerivedClass; 
base[1] = new SecondDerivedClass; 

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

  • कोई संबंधित समस्या नहीं^_^