2012-08-09 10 views
5

शीर्षक यह सब कुछ कहता है। असल में, यह कानूनी ऐसा करने के लिए है:सी ++: वेक्टर <Base> में व्युत्पन्न प्रकार की वस्तुएं हो सकती हैं?

class Base { 
    //stuff 
} 

class Derived: public Base { 
    //more stuff 
} 

vector<Base> foo; 
Derived bar; 
foo.push_back(bar); 

अन्य पदों मैंने देखा है के आधार पर, निम्न ठीक है, लेकिन मैं क्योंकि यह सुरक्षित धागा बनाने के लिए कठिन है इस मामले में संकेत का उपयोग नहीं करना चाहते हैं ।

vector<Base*> foo; 
Derived* bar = new Derived; 
foo.push_back(bar); 
+0

क्यों thread- है सुरक्षा किसी भी तरह से प्रासंगिक यहाँ? क्या आपका मतलब अपवाद-सुरक्षा शायद था? यदि हां, तो, 'push_back' एक अपवाद फेंक सकता है, जो एक खतरनाक सूचक को छोड़ देता है। आप इसे संभालने के लिए स्मार्ट पॉइंटर्स का उपयोग कर सकते हैं। – DanielKO

+0

@DanielKO मैं एक निर्माता और उपभोक्ता धागे के बीच एक बफर के रूप में एक एसटीएल कंटेनर का उपयोग कर रहा हूँ। मैं कंटेनर को पॉइंटर्स से भरना नहीं चाहता हूं क्योंकि भले ही मैंने कंटेनर को म्यूटेक्स से सुरक्षित रखा हो, भले ही किसी थ्रेड में किसी अन्य डेटा के पॉइंटर हों, तो डेटा सुरक्षित नहीं है। – Beezum

+0

वह स्वयं थ्रेड-सुरक्षा समस्या नहीं है। पॉइंटर्स के बिना भी कोई थ्रेड-असुरक्षित तरीके से तत्वों के साथ गड़बड़ कर सकता है। आपको केवल उचित अर्थशास्त्र परिभाषित करना है ताकि सामग्री (पॉइंटर्स या सीधे के रूप में संग्रहीत) उचित समरूपता स्थिरता तंत्र के बिना संशोधित नहीं की जा सके। विशेष रूप से, यदि आप डरते हैं कि कक्षा का कोई उपयोगकर्ता "अनुमति" के बिना तत्व को पॉइंटर स्टोर कर सकता है, तो आपको क्या लगता है कि वह एक सूचक या संदर्भ को उसी तरह नहीं लेगा? – DanielKO

उत्तर

13

नहीं, Derived ऑब्जेक्ट्स sliced होंगे: सभी अतिरिक्त सदस्यों को त्याग दिया जाएगा।

कच्चे पॉइंटर्स के बजाय, std::vector<std::unique_ptr<Base> > का उपयोग करें।

+0

@LuchianGrigore "वेक्टर में व्युत्पन्न प्रकार की वस्तुएं हो सकती हैं?" -> नहीं, उन्हें कटाया जाएगा, इसलिए वे सिर्फ 'बेस' ऑब्जेक्ट्स होंगे। यह अवैध नहीं है, लेकिन यह भी सच नहीं है। – mfontanini

+1

@LuchianGrigore "नहीं, वेक्टर में व्युत्पन्न प्रकार की वस्तुएं शामिल नहीं हो सकती हैं"। क्योंकि एक बार जब वे कटा हुआ हो जाते हैं तो वे अब 'व्युत्पन्न' नहीं होते हैं। – ecatmur

+1

@ हेसेनबग 'बेस' जो कि वेक्टर में समाप्त होता है वह 'व्युत्पन्न' ऑब्जेक्ट से बनाई गई प्रतिलिपि बनाई गई है। यदि एक प्रति निर्माण एक रिसाव उत्पन्न करता है, तो आपको अपने कोड में एक समस्या है: डी। – mfontanini

4

यह कानूनी है, लेकिन वस्तु टुकड़ा करने की क्रिया से ग्रस्त है। असल में, आपके पास Base ऑब्जेक्ट्स का वेक्टर होगा। कोई बहुलक नहीं, व्युत्पन्न वस्तुओं के लिए प्रकार की जानकारी खो जाएगी ... ऐसा लगता है कि आप वेक्टर में Base ऑब्जेक्ट्स जोड़ रहे होंगे।

आप इसके बजाए स्मार्ट पॉइंटर्स का उपयोग कर सकते हैं।

0
vector<Base> foo; 
Derived bar; 
foo.push_back(bar); 

यह बेस वस्तु धक्का के बराबर है, क्योंकि push_back इस तरह घोषित किया जाता है:

void push_back (const T& x); 

तो, संकलक निहित पदावनति रूपांतरण करना होगा और वेक्टर स्मृति पूल में कॉपी कर सकता हूँ। नहीं, vector<Base> के अंदर Derived रखना संभव नहीं है। वे Base होंगे।

आप तो Base करने के लिए कुछ आभासी समारोह जोड़ने Derived ओवरराइड, Derived वस्तु बनाने के लिए, यह vector<Base> में धक्का और फिर इसे वेक्टर की नई वस्तु से कॉल करते हैं, आप देखेंगे कि Base कार्यान्वयन कहा जाता है

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