आप इन जवाब के साथ hypotheticals में हो रही है, तो मैं स्पष्टता की खातिर एक सरल, पृथ्वी स्पष्टीकरण के लिए नीचे अधिक बनाने के लिए कोशिश करेंगे।
वस्तु उन्मुख डिजाइन के बुनियादी रिश्तों दो हैं: IS-एक है और एक। मैंने उन्हें नहीं बनाया। यही वह है जिसे उन्हें बुलाया जाता है।
IS-एक इंगित करता है कि एक विशेष वस्तु वर्ग एक वर्ग पदानुक्रम में यह ऊपर है कि के होने के रूप में पहचानती है। एक केला वस्तु एक फल वस्तु है यदि यह फल वर्ग का उप-वर्ग है। इसका मतलब है कि कहीं भी एक फल वर्ग का उपयोग किया जा सकता है, केले का उपयोग किया जा सकता है। हालांकि, यह रिफ्लेक्सिव नहीं है। यदि आप उस विशिष्ट वर्ग के लिए बुलाए जाते हैं तो आप किसी विशिष्ट वर्ग के लिए बेस क्लास को प्रतिस्थापित नहीं कर सकते हैं।
है-एक संकेत दिया है कि एक वस्तु एक समग्र वर्ग का हिस्सा है और एक स्वामित्व संबंध नहीं है। इसका अर्थ यह है कि सी ++ में यह एक सदस्य वस्तु है और इस तरह के मालिक स्वयं को नष्ट करने से पहले स्वामित्व को बंद करने के लिए स्वामित्व वाले वर्ग पर हैं।
सी ++ जैसे एकाधिक विरासत मॉडल की तुलना में इन दो अवधारणाओं को एकल विरासत भाषाओं में महसूस करना आसान है, लेकिन नियम अनिवार्य रूप से वही हैं। जटिलता तब आती है जब कक्षा की पहचान संदिग्ध होती है, जैसे कि केले वर्ग सूचक को फ़ंक्शन क्लास पॉइंटर ले जाने वाले फ़ंक्शन में गुजरना।
वर्चुअल फ़ंक्शंस, सबसे पहले, रन-टाइम चीज हैं। यह बहुरूपता का हिस्सा है जिसमें इसका उपयोग यह तय करने के लिए किया जाता है कि उस समय चलने वाले कार्यक्रम में किस समारोह को चलाने के लिए चलाया जाता है।
आभासी कीवर्ड एक निश्चित क्रम में कार्यों बाध्य करने के लिए अगर वहाँ वर्ग की पहचान के बारे में अस्पष्टता है एक संकलक निर्देश है। वर्चुअल फ़ंक्शंस हमेशा अभिभावक वर्गों (जहां तक मुझे पता है) में होते हैं और संकलक को इंगित करते हैं कि उनके नामों के लिए सदस्य फ़ंक्शंस को बाध्यकारी पहले सबक्लास फ़ंक्शन के साथ और पैरेंट क्लास फ़ंक्शन के बाद होना चाहिए।
एक फल वर्ग एक आभासी समारोह रंग() कि "कुछ नहीं" देता है डिफ़ॉल्ट रूप से हो सकता था। केला वर्ग रंग() फ़ंक्शन "पीला" या "ब्राउन" देता है।
लेकिन समारोह एक फल सूचक ले रही है यह करने के लिए भेजा केले वर्ग पर रंग() कॉल - जो रंग() फ़ंक्शन लागू हो जाता है? फ़ंक्शन सामान्य रूप से फल ऑब्जेक्ट के लिए Fruit :: color() को कॉल करेगा।
वह 99% समय का इरादा नहीं था। लेकिन अगर फल :: रंग() को वर्चुअल घोषित किया गया था तो केला: रंग() वस्तु के लिए कहा जाएगा क्योंकि सही रंग() फ़ंक्शन कॉल के समय फल सूचक से बंधेगा। रनटाइम जांच करेगा कि पॉइंटर पॉइंट किस ऑब्जेक्ट को इंगित करता है क्योंकि इसे फ्रूट क्लास परिभाषा में वर्चुअल चिह्नित किया गया था।
यह सबक्लास में किसी फ़ंक्शन को ओवरराइड करने से अलग है। उस मामले में फल सूचक फलों :: रंग() को कॉल करेगा यदि यह सब जानता है कि यह फल के लिए एक सूचक है।
तो अब "शुद्ध वर्चुअल फ़ंक्शन" के विचार के लिए आता है। यह एक दुर्भाग्यपूर्ण वाक्यांश है क्योंकि शुद्धता के साथ इसका कोई लेना-देना नहीं है। इसका मतलब है कि इसका उद्देश्य है कि बेस क्लास विधि को कभी भी नहीं कहा जाना चाहिए। वास्तव में एक शुद्ध वर्चुअल फ़ंक्शन नहीं कहा जा सकता है। हालांकि, इसे अभी भी परिभाषित किया जाना चाहिए। एक फ़ंक्शन हस्ताक्षर मौजूद होना चाहिए। कई कोडर पूर्णता के लिए खाली कार्यान्वयन {} बनाते हैं, लेकिन संकलक आंतरिक रूप से उत्पन्न नहीं करेगा यदि नहीं। उस स्थिति में जब फंक्शन को फल कहा जाता है तो भी कहा जाता है, केले :: रंग() को कॉल किया जाएगा क्योंकि यह रंग() का एकमात्र कार्यान्वयन है।
अब पहेली का अंतिम भाग: रचनाकार और विनाशक।
शुद्ध वर्चुअल कंस्ट्रक्टर अवैध, पूरी तरह से अवैध हैं। वह बस बाहर है।
लेकिन शुद्ध वर्चुअल विनाशक इस मामले में काम करते हैं कि आप बेस क्लास इंस्टेंस के निर्माण को रोकना चाहते हैं। बेस वर्ग के विनाशक शुद्ध वर्चुअल होने पर केवल उप वर्गों को तत्काल किया जा सकता है। सम्मेलन 0.
virtual ~Fruit() = 0; // pure virtual
Fruit::~Fruit(){} // destructor implementation
आप इस मामले में एक कार्यान्वयन बनाने के लिए क्या है निर्दिष्ट करने के लिए है। संकलक जानता है कि यह वही है जो आप कर रहे हैं और यह सुनिश्चित करता है कि आप इसे सही करते हैं, या यह दृढ़ता से शिकायत करता है कि यह संकलित करने के लिए आवश्यक सभी कार्यों से लिंक नहीं हो सकता है। त्रुटियां भ्रमित हो सकती हैं यदि आप सही वर्ग पर नहीं हैं कि आप अपनी कक्षा पदानुक्रम का मॉडल कैसे कर रहे हैं।
तो आप इस मामले में फल के उदाहरण बनाने के लिए मना कर रहे हैं, लेकिन केले के उदाहरण बनाने की अनुमति दी।
केला के उदाहरण को इंगित करने वाले फल सूचक को हटाने के लिए कॉल केले :: ~ केले() पहले कॉल करेगा और फिर हमेशा Fuit :: ~ Fruit() को कॉल करेगा। कोई फर्क नहीं पड़ता कि, जब आप एक उप-वर्ग विनाशक कहते हैं, तो बेस क्लास विनाशक का पालन करना चाहिए।
क्या यह एक खराब मॉडल है? यह डिज़ाइन चरण में अधिक जटिल है, हां, लेकिन यह सुनिश्चित कर सकता है कि रन-टाइम पर सही लिंकिंग किया जाता है और एक उप-वर्ग कार्य निष्पादित किया जाता है जहां अस्पष्टता है कि वास्तव में किस सबक्लास का उपयोग किया जा रहा है।
यदि आप सी ++ लिखते हैं ताकि आप केवल सामान्य क्लाइंट पॉइंटर्स के पास पास न हों, न कि कोई सामान्य और न ही अस्पष्ट पॉइंटर्स, तो वर्चुअल फ़ंक्शंस की वास्तव में आवश्यकता नहीं होती है। लेकिन यदि आपको प्रकार के रन-टाइम लचीलापन की आवश्यकता होती है (जैसे ऐप्पल केले ऑरेंज ==> फल) फ़ंक्शन कम अनावश्यक कोड के साथ आसान और अधिक बहुमुखी हो जाते हैं। आपको अब प्रत्येक प्रकार के फल के लिए कोई फ़ंक्शन लिखना नहीं है, और आप जानते हैं कि प्रत्येक फल रंग() को अपने स्वयं के सही कार्य के साथ प्रतिसाद देगा।
मुझे आशा है कि यह लंबी हवा वाली स्पष्टीकरण चीजों को भ्रमित करने के बजाय अवधारणा को मजबूत करेगी। पर देखने के लिए बहुत अच्छे उदाहरण हैं और पर्याप्त रूप से देखें और वास्तव में उन्हें चलाएं और उनके साथ गड़बड़ करें और आपको यह मिल जाएगा।
एकाधिक डुप्लीकेट: http://stackoverflow.com/questions/999340/question-about-pure-virtual-destructor और http://stackoverflow.com/questions/630950/pure-virtual-destructor-in-c उनमें से दो होने के नाते –
@ डैनियल- उल्लिखित लिंक मेरे प्रश्न का उत्तर नहीं देते हैं। यह जवाब देता है कि एक शुद्ध आभासी विनाशक की परिभाषा क्यों होनी चाहिए। मेरा सवाल यह है कि हमें शुद्ध वर्चुअल विनाशक की आवश्यकता क्यों है। – Mark
मैं कारण जानने का प्रयास कर रहा था, लेकिन आप पहले से ही सवाल पूछ चुके हैं। – user373215