2012-06-19 12 views
5

नहीं कहा जा रहा है मेरे पास पैनल नामक आधार श्रेणी है, जहां खिड़की के बारे में कुछ जानकारी संग्रहीत की जाती है, फिर मेरे पास सभी नियंत्रणों के लिए उप-वर्ग हैं: बटन, लेबल इत्यादि। बेस क्लास में, मेरे पास virtual void ApplySchemeSettings(Scheme* scheme) { } विधि है , जिसे Panel(Panel* parent) कन्स्ट्रक्टर के भीतर बुलाया जाता है। लेकिन उप-वर्ग के बजाय, बेस क्लास से ApplySchemeSettings (Panel) कहा जा रहा है।वर्चुअल विधि को

class Panel 
{ 
    [...] 

public: 
    virtual void ApplySchemeSettings(Scheme* scheme) { }; 

    Panel(Panel* parent) 
    { 
     [...] 

     this->ApplySchemeSettings(scheme()); 
    }; 
} 

class Frame : public Panel 
{ 
    [...] 

public: 
    void ApplySchemeSettings(Scheme* scheme) 
    { 
     this->border = scheme->GetBorder("FrameBorder"); 
    } 
} 

मैं ApplySchemeSettings के रूप में सार की घोषणा नहीं कर सकते क्योंकि उपवर्गों उपयोगकर्ता द्वारा किया जाता है।

+1

'यह-> ApplySchemeSettings (योजना()); 'कॉल के बिंदु पर' इस 'पॉइंटर का प्रकार' पैनल * const' है, इसलिए यह 'पैनल :: ApplySchemeSettings' को आमंत्रित करता है। कहानी का नैतिक आधार वर्ग के निर्माता से कभी वर्चुअल फ़ंक्शन नहीं कॉल करता है। –

+0

http://stackoverflow.com/questions/6582239/avoiding-virtual-methods-in-constructor –

+0

http://stackoverflow.com/questions/507043/virtual-function-invocation-from-constructor –

उत्तर

8

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

आपको इस समस्या को हल करने के लिए कुछ और दृष्टिकोण खोजने की आवश्यकता होगी। उदाहरण के लिए, आप दो-चरणीय निर्माण कर सकते हैं जिसमें आप कन्स्ट्रक्टर को कॉल करने के बाद कुछ init() विधि कॉल करते हैं। हालांकि, कन्स्ट्रक्टर से वर्चुअल फ़ंक्शन के सबसे व्युत्पन्न संस्करण को सुरक्षित रूप से कॉल करने का कोई तरीका नहीं है।

आशा है कि इससे मदद मिलती है!

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