2010-06-04 13 views
6

इस कोड है:सी ++ में ऑब्जेक्ट स्लाइसिंग के लिए संभावित कार्यवाही क्या है?

#include <string> 
#include <vector> 
#include <iostream> 
using namespace std; 
class A { 
public: 
    virtual const string f() const { return "A"; } 
}; 
class B : public A { 
public: 
    const string f() const { return "B"; } 
}; 
int main(int ac, char** av) { 
    vector<A> v; 
    v.push_back(B()); 
    cout << v.at(0).f() << endl; 
    return 0; 
} 

अपेक्षित परिणाम B है, लेकिन यह A है। जैसा कि मैं समझता हूं ऑब्जेक्ट स्लाइसिंग हो रहा है। इससे कैसे बचें? क्या मैं ऑब्जेक्ट इंस्टेंस के बजाय vector में पॉइंटर्स स्टोर करूं? क्या यह एकमात्र विकल्प है?

+0

ऑब्जेक्ट स्लाइसिंग, हालांकि यहां हो रहा है, गलत परिणाम का कारण नहीं है, यह सदस्य ऑपरेटर (।) द्वारा फ़ंक्शन आमंत्रण है। वर्चुअल फ़ंक्शंस को सदस्य-बाय-पॉइंटर ऑपरेटर (->) (को छोड़कर) संदर्भों का उपयोग करते समय) – Ozan

+6

@ ओज़न: बकवास। किसी अन्य सदस्य फ़ंक्शन (आभासी या नहीं) से वर्चुअल सदस्य फ़ंक्शन को कॉल करने से वर्चुअल कॉल भी होगा। – MSalters

+0

हां, मैं सिर्फ विनसेन्जो को इंगित करना चाहता था कि सदस्य ऑपरेटर का उपयोग करके, स्लाइसिंग ऑब्जेक्ट नहीं, अपराधी था। यह एक आम गलती है जब जावा/सी # लोग सी ++ – Ozan

उत्तर

11

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

3

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

11

, सबसे सरल से आदेश दिया सबसे जटिल (लेकिन अधिकांश अच्छा) के लिए।

समाधान 1:

vector<B> v; 
v.push_back(B()); 
cout << v.at(0).f() << endl; 

समाधान 2:

vector<A*> v; 
v.push_back(new B()); 
cout << v.at(0)->f() << endl; 
while(!v.empty()) { delete v.back(); v.pop_back(); } 

समाधान 3:

vector<boost::shared_ptr<A>> v; 
v.push_back(boost::make_shared<B>()); 
cout << v.at(0)->f() << endl; 

आप w नहीं करते हैं चींटी टुकड़ा होने के लिए, आपको इस तथ्य को ध्यान में रखना होगा कि अलग-अलग वस्तुओं के अलग-अलग आकार हो सकते हैं - ergo आपको एक ऐसे समाधान की आवश्यकता है जो परिवर्तनीय आकारों के साथ काम कर सके - जो ढेर पर भंडारण कर लेता है।

+2

वेक्टर > v; 'वास्तव में बुरा विचार है। किसी वेक्टर में 'auto_ptr' को कभी भी स्टोर न करें, क्योंकि इसकी प्रतिलिपि सीटीओ पारित वस्तु को संशोधित करती है। कारण के लिए //www.gotw.ca/publications/using_auto_ptr_effectively.htm: http: इस देखें। – Naveen

+0

@ नवीन, मुझे पता है, फिर भी यह एकमात्र प्री-टीआर 1 स्मार्ट पॉइंटर है। –

+0

मुझे यकीन है कि यह वास्तव में _forbidden_ ​​ऐसा करने के लिए है। 'std :: auto_ptr' एक कंटेनर तत्व के लिए आवश्यकताओं को पूरा नहीं करता है। – sbi

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