OOP, कंस्ट्रक्टर और डिस्ट्रक्टर्स के बारे में बात करने के बाद, अब वर्चुअल डिस्ट्रक्टर्स के बारे में बात करते हैं। आभासी विध्वंसक, जैसा कि नाम निर्दिष्ट करता है, वस्तु को नष्ट कर देता है। हमारे पास एक आधार वर्ग और एक व्युत्पन्न वर्ग है जो आधार वर्ग से प्राप्त होता है। दोनों वर्गों के अपने निर्माता और विध्वंसक हैं। वर्चुअल डिस्ट्रक्टर 'वर्चुअल' कीवर्ड के साथ बेस क्लास पॉइंटर का उपयोग करके व्युत्पन्न वर्ग की वस्तुओं को हटाते समय स्मृति को मुक्त करता है जो व्युत्पन्न वर्ग वस्तु के माध्यम से आवंटित किया जाता है।
हम वर्चुअल डिस्ट्रक्टर का उपयोग क्यों करते हैं?
जब वर्ग सदस्य कार्यों का निष्पादन पूरा हो जाता है या मुख्य () विधि का निष्पादन समाप्त होने वाला होता है, तो ऑब्जेक्ट निर्माण के दौरान आवंटित की गई मेमोरी को मुक्त करने के लिए विध्वंसक को स्वचालित रूप से बुलाया जाता है। अब, हम आभासी विनाशक का उपयोग क्यों करते हैं? जब आधार वर्ग हटा दिया जाता है जो व्युत्पन्न वर्ग को इंगित करता है, तो सूचक (*) का उपयोग यहां किया जाता है। बेस क्लास डिस्ट्रक्टर को केवल इस प्रक्रिया के दौरान ही बुलाया जाता है। व्युत्पन्न वर्ग विनाशक नहीं कहा जाता है जो मुद्दों की ओर जाता है। उनमें से एक मेमोरी लीकेज मुद्दा है। इस समस्या से बचने के लिए और अपने कोड को सुरक्षित बनाने के लिए, हम बेस क्लास डिस्ट्रक्टर को हटाकर ऑब्जेक्ट के निर्माण के दौरान आवंटित मेमोरी स्पेस को खाली करने के लिए ऑब्जेक्ट को वस्तुतः नष्ट कर देते हैं।
वर्चुअल विनाशक के बिना सी ++ मूल उदाहरण
आइए देखें कि पॉइंटर को हटाने वाले एक साधारण प्रोग्राम के साथ वर्चुअल डिस्ट्रक्टर के बिना प्रोग्राम कैसे काम करता है।
कोड:
#शामिलनेमस्पेस एसटीडी का उपयोग करना ;
वर्ग जनक_Class0
{
जनता :
जनक_कक्षा0 ( )
{ अदालत << 'जनक वर्ग निर्माता' << endl ; }
~ जनक_वर्ग0 ( )
{ अदालत << 'जनक वर्ग विनाशक' << endl ; }
} ;
क्लास चाइल्ड_1 : पब्लिक पेरेंट_क्लास0
{
जनता :
चाइल्ड_1 ( )
{ अदालत << 'चाइल्ड क्लास कंस्ट्रक्टर' << endl ; }
~बच्चा_1 ( )
{ अदालत << 'चाइल्ड क्लास डिस्ट्रक्टर' << endl ; }
} ;
पूर्णांक मुख्य ( )
{
जनक_कक्षा0 * सूचक = नया बच्चा_1 ( ) ;
संकेतक हटाएं ;
वापसी 0 ;
}
यह कोड बताता है कि वर्चुअल विनाशक के बिना कोड कैसे निष्पादित होता है। सबसे पहले, “Parent_Class0” नाम से एक क्लास बनाएं जो पैरेंट क्लास होगी। इस क्लास के अंदर कंस्ट्रक्टर और डिस्ट्रक्टर बनाएं। जैसा कि हम जानते हैं कि कंस्ट्रक्टर और डिस्ट्रक्टर का नाम क्लास के समान ही होता है। डिस्ट्रक्टर को कंस्ट्रक्टर के समान दर्शाया जाता है लेकिन इसमें एक प्रतीक (~) होता है जो इसे कंस्ट्रक्टर से अलग करता है। कंस्ट्रक्टर और डिस्ट्रक्टर के अंदर, 'cout <<' का उपयोग करके एक संदेश प्रिंट करें। अब, एक और वर्ग बनाएं जो 'चाइल्ड_1' है। यह वर्ग मूल वर्ग, 'Parent_Class0' से लिया गया है। व्युत्पन्न वर्ग में इसके निर्माता और विध्वंसक होते हैं जिनमें आउटपुट स्क्रीन पर प्रिंट करने के लिए एक संदेश होता है।
मुख्य () विधि में, हम 'Parent_Class0' का एक उदाहरण बनाते हैं और इसे एक व्युत्पन्न वर्ग प्रदान करते हैं। इस मामले में याद रखने वाली महत्वपूर्ण बात यह है कि हम मूल वर्ग को पुनः प्राप्त करने के लिए एक सूचक का उपयोग करते हैं। जब यह पैरेंट क्लास के अंदर जाता है, तो यह पैरेंट क्लास कंस्ट्रक्टर को निष्पादित करता है। फिर, यह चाइल्ड क्लास में जाता है और इसके कंस्ट्रक्टर को निष्पादित करता है। उपवर्ग के विध्वंसक को निष्पादित करने से पहले, उसे मूल वर्ग के विध्वंसक को निष्पादित करना होगा। कंपाइलर पैरेंट क्लास के डिस्ट्रक्टर को निष्पादित करता है और चाइल्ड क्लास के डिस्ट्रक्टर को निष्पादित किए बिना क्लास को समाप्त कर देता है। यही दिक्कत है; यह बच्चे की कक्षा की याददाश्त को मुक्त नहीं करता है। यह पैरेंट क्लास के कंस्ट्रक्टर, चाइल्ड क्लास के कंस्ट्रक्टर और पैरेंट क्लास के डिस्ट्रक्टर का प्रतिनिधित्व करता है। इससे पता चलता है कि बाल वर्ग के विनाशक को निष्पादित नहीं किया जाता है। इस निष्पादन के बाद, हम सूचक को मुख्य () फ़ंक्शन में हटा देते हैं।
आउटपुट:
वर्चुअल विनाशक के साथ सी ++ उदाहरण
वर्चुअल डिस्ट्रक्टर के साथ और उसके बिना कैसे काम करता है, यह अंतर करने के लिए एक सरल कोड के साथ वर्चुअल डिस्ट्रक्टर पर चर्चा करें।
कोड:
#शामिलनेमस्पेस एसटीडी का उपयोग करना ;
वर्ग जनक_Class0
{
जनता :
जनक_कक्षा0 ( )
{ अदालत << 'जनक वर्ग निर्माता' << endl ; }
आभासी ~ Parent_Class0 ( )
{ अदालत << 'जनक वर्ग विनाशक' << endl ; }
} ;
क्लास चाइल्ड_1 : पब्लिक पेरेंट_क्लास0
{
जनता :
चाइल्ड_1 ( )
{ अदालत << 'चाइल्ड क्लास कंस्ट्रक्टर' << endl ; }
वर्चुअल ~ चाइल्ड_1 ( )
{ अदालत << 'चाइल्ड क्लास डिस्ट्रक्टर' << endl ; }
} ;
पूर्णांक मुख्य ( )
{
जनक_कक्षा0 * सूचक = नया बच्चा_1 ( ) ;
संकेतक हटाएं ;
वापसी 0 ;
}
पहले कार्यक्रम ने उस समस्या की व्याख्या की जिसका हम बिना आभासी विध्वंसक के सामना कर रहे हैं। अब, यह कोड वर्चुअल विनाशक का उपयोग करके उस समस्या को हल करेगा। सबसे पहले, पहले कोड को कॉपी करें और इस प्रोग्राम में केवल एक कीवर्ड को दो स्थानों पर जोड़ें। वह शब्द 'आभासी' है। इस शब्द को मूल वर्ग के विनाशक, 'पेरेंट_क्लास0' के साथ डालें। इसी प्रकार, इसका उल्लेख बाल वर्ग के विनाशक के साथ करें जो 'चाइल्ड_1' है जो मूल वर्ग से लिया गया है। यह 'वर्चुअल' कीवर्ड थोड़ा बदलाव करता है और यह पहले 'चाइल्ड_1' चाइल्ड क्लास के विध्वंसक को निष्पादित करता है। फिर, यह मूल वर्ग, 'पेरेंट_क्लास0' के विध्वंसक को निष्पादित करता है। शेष कार्यक्रम उसी तरह संचालित होता है जैसे यह वर्चुअल विनाशक के बिना संचालित होता है। इस छोटे से कोड को जोड़कर हम अपनी मेमोरी को लीक होने से बचा सकते हैं। अब, यह कंसोल पर चार संदेश प्रदर्शित करता है। पहले पैरेंट क्लास का कंस्ट्रक्टर, फिर चाइल्ड क्लास का कंस्ट्रक्टर, चाइल्ड क्लास का डिस्ट्रक्टर और पैरेंट क्लास का डिस्ट्रक्टर। अंत में, हम main() मेथड के भीतर पॉइंटर को हटाते हैं।
आउटपुट:
C++ प्योर वर्चुअल डिस्ट्रक्टर का उदाहरण
इस कोड में, हम शुद्ध आभासी विध्वंसक के बारे में बात करेंगे, यह कैसे काम करता है और यह आभासी विध्वंसक से कैसे भिन्न है।
कोड:
#शामिलवर्ग जनक_0 {
जनता :
वर्चुअल ~ पैरेंट_0 ( ) = 0 ;
} ;
जनक_0 :: ~जनक_0 ( )
{
कक्षा :: अदालत << 'हैलो, मैं शुद्ध विनाशक हूं। आपने मुझे बुलाया!' ;
}
क्लास चाइल्ड_0 : सार्वजनिक जनक_0 {
जनता :
~बच्चा_0 ( ) { कक्षा :: अदालत << 'व्युत्पन्न नाशक यहाँ है \एन ' ; }
} ;
पूर्णांक मुख्य ( )
{
जनक_0 * पीटीआर_0 = नया बच्चा_0 ( ) ;
ptr_0 हटाएं ;
वापसी 0 ;
}
कोड के पहले चरण में मूल वर्ग 'पेरेंट_0' बनाया गया है। इसके अंदर, वर्चुअल पैरेंट डिस्ट्रक्टर बनाएं और इसे 0 के साथ असाइन करें। यह वर्चुअल डिस्ट्रक्टर को शुद्ध वर्चुअल डिस्ट्रक्टर पर सेट करता है, जिसका अर्थ है कि पैरेंट क्लास अब सार है और हम इस क्लास के उदाहरण नहीं बना सकते हैं। मूल वर्ग 'पेरेंट_0' के बाहर, विध्वंसक और std :: cout को परिभाषित करें। आवश्यक पाठ std::cout का उपयोग करके दिखाया गया है। फिर, मूल वर्ग से 'चाइल्ड_0' वर्ग प्राप्त करें और इसके विध्वंसक को परिभाषित करें। विनाशक के अंदर, एक संदेश प्रिंट करें। मुख्य () फ़ंक्शन में, पैरेंट क्लास का पॉइंटर बनाएं और उसे चाइल्ड क्लास असाइन करें।
कंपाइलर पैरेंट क्लास 'पेरेंट_0' में जाता है। जब पॉइंटर बनाया जाता है, तो इसका कंस्ट्रक्टर अपने आप कॉल हो जाता है। फिर, कंपाइलर अपने कंस्ट्रक्टर को आमंत्रित करने के लिए चाइल्ड क्लास में जाता है। कंस्ट्रक्टर के सफल निष्पादन के बाद, यह चाइल्ड क्लास 'चाइल्ड_0' के विध्वंसक को निष्पादित करता है। फिर, यह मूल वर्ग के विनाशक को निष्पादित करता है। इस तरह, हम एक शुद्ध आभासी विध्वंसक बना सकते हैं। इसका उपयोग करने के लिए प्रोत्साहित नहीं किया जाता है क्योंकि इस पद्धति को नियोजित करने से मूल वर्ग अमूर्त हो जाता है जो इसे बेकार बना देता है। अधिकतर उपयोग की जाने वाली पद्धति वर्चुअल विनाशक है और यह एक अच्छा अभ्यास है।
आउटपुट:
निष्कर्ष
हमने वर्चुअल डिस्ट्रक्टर के बारे में OOP की अवधारणा से शुरू होकर कंस्ट्रक्टर और डिस्ट्रक्टर की ओर बढ़ने के बारे में सीखा। इन सभी को समझाने के बाद हमने कोडिंग उदाहरणों और शुद्ध वर्चुअल डिस्ट्रक्टर के साथ वर्चुअल डिस्ट्रक्टर के बारे में विस्तार से चर्चा की। वर्चुअल डिस्ट्रक्टर की व्याख्या करने से पहले, हमें कंस्ट्रक्टर, डिस्ट्रक्टर और इनहेरिटेंस के बारे में पता होना चाहिए। विरासत में, हम मूल वर्ग से कक्षाएं प्राप्त करते हैं। चाइल्ड क्लास एक से ज्यादा हो सकती है लेकिन पैरेंट क्लास एक ही होती है। मेमोरी लीकेज से बचाने के लिए वर्चुअल डिस्ट्रक्टर्स और प्योर वर्चुअल डिस्ट्रक्टर्स को इनहेरिटेंस में लगाया जाता है। मूल उदाहरण से लेकर उन्नत उदाहरण तक, हमने वह सब कुछ शामिल किया है जो आपको व्युत्पन्न वर्ग की स्मृति का उपयोग शुरू करने और वस्तुतः नष्ट करने के लिए जानना चाहिए।