2011-06-05 16 views
5

मान लीजिए कि मेरे पास वर्चुअल फ़ंक्शन और व्युत्पन्न क्लास वाला क्लास है जो वर्चुअल फ़ंक्शन को एक अलग तरीके से लागू करता है। मान लीजिए कि मेरे पास व्युत्पन्न कक्षाओं को संग्रहीत करने के लिए उपयोग की जाने वाली बेस क्लास का वेक्टर भी है। मैं वेक्टर में व्युत्पन्न कक्षा के वर्चुअल फ़ंक्शन को कैसे पहले से जाने बिना व्युत्पन्न कक्षा क्या करूँगा? न्यूनतम कोड जो समस्या को दर्शाता है:सी ++: व्युत्पन्न वर्ग के वर्चुअल फ़ंक्शन को कॉल करना

#include <iostream> 
#include <vector> 

class Foo { 
public: 
    virtual void do_stuff (void) { 
     std::cout << "Foo\n"; 
    } 
}; 

class Bar: public Foo { 
public: 
    void do_stuff (void) { 
     std::cout << "Bar\n"; 
    } 
}; 

int main (void) { 
    std::vector <Foo> foo_vector; 
    Bar bar; 

    foo_vector.resize (1); 
    foo_vector [0] = bar; 

    bar.do_stuff();   /* prints Bar */ 
    foo_vector [0].do_stuff(); /* prints Foo; should print Bar */ 
    return 0; 
} 
+7

ऑब्जेक्ट स्लाइसिंग से बचने के लिए शायद 'std :: vector ' (पॉइंटर या संदर्भ द्वारा) का उपयोग कर? अन्यथा, जिस पल में आप वेक्टर को 'बार' ऑब्जेक्ट असाइन करते हैं, इसे काटा गया है (एक नया 'फू' बनाया गया है और आपके 'बार' के बजाय वेक्टर में संग्रहीत किया गया है), जो शायद आप नहीं चाहते हैं। पॉइंटर का उपयोग कोड को और अधिक जटिल बना देगा, हालांकि। – rwong

उत्तर

14

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

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

+2

धन्यवाद। मैं टुकड़ा करने से अनजान था, और आपके सुझाव ने समस्या हल की। – Adetque

2

जिस कक्षा में आप वास्तव में कॉल कर रहे हैं वह बार की कक्षा नहीं है, बल्कि इसके बजाय फू का एक वर्ग है। foo_vector [0] = bar; पर आप क्या कर रहे हैं निहित ऑपरेटर का एक कॉल है जो कुछ स्मार्ट होने के लिए अपनी पूरी कोशिश कर रहा है। मेमोरी स्पेस अभी भी एक फू का आकार है, इसलिए यह कभी भी बार नहीं हो सकता है।

0

वर्चुअल फ़ंक्शंस का उपयोग करते समय, आप ऑब्जेक्ट्स के पॉइंटर्स का उपयोग करते हैं। इस तरह सटीक फ़ंक्शन को रन टाइम के दौरान बुलाया जाता है ("वे व्युत्पन्न कक्षा के व्युत्पन्न वर्ग के आभासी फ़ंक्शन को कैसे पहले से जाने बिना व्युत्पन्न कक्षा क्या है?" यहां आपका क्या मतलब है "रन टाइम")।

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

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