C++ में प्रोग्रामिंग के मॉड्यूल(module) 31 में आपका स्वागत है। डायनामिक(dynamic) बाइंडिंग(binding), पोलीमोर्फिज्म(polymorphism) के बारे में हमने पिछले कुछ मॉड्यूल(module) में चर्चा की है, हमने चर्चा की है कि पोलीमोर्फिज्म(polymorphism) क्या है और विशेष रूप से प्रमुख नई विशेषता जो हमने सीखी है वह पॉलीमोर्फिक(polymorphic) प्रेषण के बारे में है। यह एक तंत्र है जिसके माध्यम से, जब मैं एक पॉलीमोर्फिक(polymorphic) पदानुक्रम(hierarchy) से संबंधित क्लास(class) के एक सदस्य(member) फ़ंक्शन(function) को कॉल करता हूं। जब मैं एक पॉइंटर(pointer) के माध्यम से या बेस क्लास प्रकार के संदर्भ के माध्यम से कॉल करता हूं, तो वास्तविक फ़ंक्शन(function)(function) का उपयोग पॉइंटर(pointer) या संदर्भ के प्रकार पर निर्भर नहीं करता है, लेकिन यह वास्तव में वर्तमान ऑब्जेक्ट(object) पर निर्भर करता है या संदर्भित होने के लिए निर्भर करता है। यह रनटाइम पर निर्भर करता है और इस तंत्र को पोलीमोर्फिज्म(polymorphism) के रूप में जाना जाता है या बाध्यकारी की इस पद्धति को डायनामिक(dynamic) बाइंडिंग(binding) के रूप में जाना जाता है जैसा कि हमने देखा है, और इस पूरी चीज को C ++ में पॉलीमोर्फिक(polymorphic) डिस्पैच के रूप में जाना जाता है। हमने पॉलीमोर्फिक(polymorphic) डिस्पैच मैकेनिज्म को देखा है और हमने इसका इस्तेमाल स्टाफ सैलरी प्रोसेसिंग के समाधान को तैयार करने में बड़े पैमाने पर किया है। मॉड्यूल(module) में, आज हम वर्चुअल(virtual) फंक्शन(function) टेबल(table) के बारे में चर्चा करेंगे, यह है कि हम इस पॉलीमोर्फिक(polymorphic) प्रेषण के संदर्भ में थोड़ी समझ लेना चाहेंगे; वास्तव में संकलक द्वारा कार्यान्वित किया गया। क्योंकि आपको यह याद रखना होगा कि कोड प्रक्रिया के समय संकलक स्थिर समय पर काम करता है; स्रोत को उस समय संसाधित किया जा रहा है जिसमें कोई निष्पादन नहीं हो रहा है। इसलिए, संकलक के पास रनटाइम पर दिए गए संकेतक के रूप में जानने का कोई तरीका नहीं है जो कि उस वस्तु का प्रकार है जिसे वह वास्तव में इंगित करेगा, लेकिन फिर भी उसे एक कोड उत्पन्न करना होगा जो निष्पादन के दौरान डायनामिक(dynamic) प्रकार के अनुसार काम करेगा। यह वर्चुअल(virtual) फंक्शन(function) टेबल(table) के उपयोग के माध्यम से किया जाता है, जो कि पॉलिमरइक प्रेषण के लिए महत्वपूर्ण है। इसके लिए हम चर्चा कर रहे वेतन प्रसंस्करण आवेदन का एक त्वरित पुनरावर्तन लेंगे। हम सी में एक नया समाधान पेश करेंगे और यह दिखाएंगे कि प्रेषण के लिए वर्चुअल(virtual) फ़ंक्शन(function) तालिका को समझने में हमें अंतर्दृष्टि कैसे मिलती है। तो यह समस्या थी, हमने मान लिया था कि विभिन्न प्रकार के कर्मचारी हैं जिनके लिए एक वेतन की आवश्यकता है और उनके वेतन प्रसंस्करण एल्गोरिदम अलग हैं। और पूरे डिज़ाइन का क्रुक्स तथ्य यह है कि डिज़ाइन को उचित रूप से एक्स्टेंसिबल होना चाहिए। जब हम ऐसा करना चाहते हैं, तो नए वर्गों को पदानुक्रम(hierarchy) में जोड़ना संभव होना चाहिए। सी में, हमने इस पर विचार किया था और आप हमेशा पहले वाले मॉड्यूल(module) का उल्लेख कर सकते हैं, उन्हें संदर्भित कर सकते हैं कि उनके पास मॉड्यूल(module) संख्या भी है और डिज़ाइन के विचार क्या हैं। अब, जब हमने उस समाधान पर चर्चा की, जिसमें हमने एक फंक्शन(function) स्विच के तंत्र का उपयोग किया था, तो क्या हम स्पष्ट रूप से उस प्रकार को बनाए रखते हैं और हर कर्मचारी के रिकॉर्ड को संसाधित करते समय हमने यह जांचा है कि एक संघ में बनाए रखने वाले प्रकार क्या हैं और फिर आधारित प्रकार पर हम उचित वेतन प्रसंस्करण कार्य कहते हैं। अब हम फ़ंक्शन(function) पॉइंटर्स(pointers) का उपयोग करके एक ही समाधान को थोड़ा अलग स्वाद के साथ देखने की कोशिश करेंगे। मुख्य अंतर जो, मैं उजागर करूंगा; निश्चित रूप से अभी भी प्रकार के स्पष्ट रखरखाव बनी हुई है। मैं सिर्फ यह मान रहा हूं कि तीन प्रकार हैं; इंजीनियर(engineer), प्रबंधक(manager) और निदेशक(director)। इससे पहले कि आप याद करते हैं कि आप वेतन प्रसंस्करण दिनचर्या को जांचने के लिए पहले वाला वीडियो या प्रस्तुति खोल सकते हैं, कहते हैं कि इंजीनियर(engineer) के लिए वेतन प्रसंस्करण इंजीनियर(engineer) के लिए एक संकेतक ले रहा था। प्रबंधक(manager) के लिए वेतन प्रसंस्करण प्रबंधक(manager) के लिए एक संकेतक ले रहा था, और निदेशक(director) को वेतन प्रसंस्करण निदेशक(director) के लिए एक संकेतक ले रहा था। अब मैंने इसे थोड़ा बदल दिया है, अब सभी एक वोईद(void) स्टार पॉइंटर(pointer) लेते हैं, क्योंकि मैं चाहता हूं कि इन सभी कार्यों में एक ही हस्ताक्षर हो। एक बार जब हम इसे स्वाभाविक रूप से वोईद(void) तारा के रूप में प्राप्त करते हैं, तो वोईद(void) तारा मुझे यह नहीं बताता है कि यह किस प्रकार की वस्तु है, लेकिन जब से मुझे पता है कि इंजीनियर(engineer) के लिए वेतन प्रसंस्करण का आह्वान किया गया है, मुझे पता है कि वोईद(void) सितारा सूचक वास्तव में एक इंजीनियर(engineer) रिकॉर्ड को इंगित करता है, इसलिए मैं इसे इंजीनियर(engineer) को दिया। या अगर यह एक प्रबंधक(manager) फ़ंक्शन(function) है, जिसे मैंने इसे प्रबंधक(manager) या निर्देशक फ़ंक्शन(function) को कॉल किया है, जिसे मैंने इसे निर्देशक को दिया है और फिर प्रसंस्करण करना है। मैं अभी भी स्पष्ट रूप से अलग-अलग पैरामीटर प्रकारों के बिना यहां प्रबंधन कर सकता हूं। लेकिन इस प्रक्रिया में एक लाभ क्या है; इस सभी कार्यों में अब एक ही हस्ताक्षर है। चूंकि उनके पास एक ही हस्ताक्षर है मैं उन्हें एक समान फ़ंक्शन(function) पॉइंटर(pointer) प्रकार के संदर्भ में संयोजित करने का प्रयास कर सकता हूं जो मैं कहता हूं कि एक ptr एक फ़ंक्शन(function) पॉइंटर(pointer) है जो एक वोईद(void) तारा लेता है और कुछ भी नहीं लिखा है। ध्यान दें कि यह एक फ़ंक्शन(function) पॉइंटर(pointer) है, इसलिए यह मूल रूप से एक फ़ंक्शन(function) पॉइंटर(pointer) प्रकार है। यह एक कार्य नहीं है। हम फ़ंक्शन(function) को परिभाषित करेंगे। तो, प्रबंधक(manager) के लिए या निर्देशक के लिए इंजीनियर(engineer) के लिए यह कोई भी कार्य वास्तव में इस फ़ंक्शन(function) पॉइंटर(pointer) प्रकार के साथ मेल खाएगा। बाकी डिज़ाइन समान हैं, विभिन्न संरचनाएं विभिन्न प्रकार की वस्तुओं को परिभाषित करने के लिए हैं और इसके साथ ही देखते हैं कि हम वास्तव में पूरी चीज़ को किस तरह से अनुप्रयोग में मिलाते हैं। आवेदन के संदर्भ में, हम क्या करते हैं, हम अब एक रिकॉर्ड बनाए रखते हैं, जहां एक पर, यह कहता है, यह मूल रूप से एक संदेह है कि यह वह जगह है जहां मैं उस प्रकार को रखता हूं, जो Er या Mgr और ऐसा ही कुछ होगा। दूसरा वोईद(void) तारा का सूचक है जो कि किसी प्रकार का सूचक है। अब हम क्या करें? हम फ़ंक्शन(function) पॉइंटर(pointer) की एक सरणी पॉप्युलेट करते हैं। तो यह एक प्रकार का फ़ंक्शन(function) पॉइंटर(pointer) है। मैंने पहले से ही एक फ़ंक्शन(function) पॉइंटर(pointer) प्रकार को परिभाषित किया है। तो यह फ़ंक्शन(function) पॉइंटस 0, 1 और 2 का एक सरणी है, और इनमें से प्रत्येक में हम वास्तव में तीन अलग-अलग फ़ंक्शन(function) असाइन करते हैं जो हमने तीन अलग-अलग संरचना प्रकारों के लिए लिखे हैं। ये वास्तव में सरणी में निर्णय लेने वाले तीन अलग-अलग फ़ंक्शन(function) पॉइंटर्स(pointers) हैं। फिर आप ऑब्जेक्ट्स(objects) के संग्रह को पॉप्युलेट करते हैं, इसलिए ऑब्जेक्ट्स का संग्रह ऑब्जेक्ट(object) प्रकार और ऑब्जेक्ट(object) इंस्टेंस है। यह ऑब्जेक्ट(object) उदाहरण के लिए एक संकेतक है ताकि वोईद(void) तारा के स्थान पर यह अब होगा। अगर मैं इस सरणी को देखता हूं तो यह दोगुना है, इसलिए मेरे पास Er है तो एक Er ऑब्जेक्ट(object), मेरे पास Mgr है, मेरे पास एक मैनेजर ऑब्जेक्ट(object) है और इसी तरह। तो हमारे पास इस तरह से होंगे, उनमें से छह अलग-अलग हैं। यह सामान मेरा कुल संग्रह है। अब, जब मैं यह प्रोसेस करना चाहता हूं कि मैं एक लूप से ऊपर जाऊंगा और यह महत्वपूर्ण है कि मैं इस फ़ंक्शन(function) पॉइंटर(pointer) ऐरे का उपयोग करूंगा और आई-वें स्टाफ के प्रकार का उपयोग करूंगा। कहो अगर i 0 है जब प्रकार Er है। मैं इस फ़ंक्शन(function) पॉइंटर(pointer) सरणी से उठाऊंगा जो कि यह सरणी है, मैं इसे इस प्रकार से अनुक्रमित करूंगा जो कि Er है जिसका अर्थ है 0 और फिर हम उस फ़ंक्शन(function) को कॉल करेंगे। तो, यह psArray अगर मैं सिर्फ एक अलग रंग का उपयोग करता हूं, तो यह कहें कि यह विशेष रूप से एक फ़ंक्शन(function) पॉइंटर(pointer) है, क्योंकि psArray यह सरणी है। मैंने इसे i डॉट प्रकार के सामान के साथ अनुक्रमित किया है जो इस मामले में Er है, पहले वाला एक इंजीनियर(engineer) है। तो मुझे जो मिलता है वह एक फ़ंक्शन(function) पॉइंटर(pointer) है जो कि एक फ़ंक्शन(function) है यह फ़ंक्शन(function) का प्रकार है, यह एक वोईद(void) तारा लेता है और फ़ंक्शन(function) को कहा जाता है। और यह जो पास करता है वह दूसरा पैरामीटर है जो यहां स्टाफ[i] .p है; वस्तु का सूचक। जब मैं इसे Er के साथ यहां बुलाता हूं, तो मुझे यह फ़ंक्शन(function) मिला है जो प्रक्रिया वेतन इंजीनियर(engineer) है इसे इंजीनियर(engineer) रिकॉर्ड द्वारा बुलाया जाएगा, यही है कि इसमें उस इंजीनियर(engineer) के साथ कॉल किया जाएगा जो रोहित के साथ किया है। जब i 1 हो जाता है, तो मुझे दूसरा रिकॉर्ड मिलता है जहां मेरे पास Mgr के रूप में टाइप होता है और जो 1 है, इसलिए मुझे दूसरा फ़ंक्शन(function) पॉइंटर(pointer) मिलता है और मैं इसे पॉइंटर(pointer) के साथ संबंधित कर्मचारी को भेजता हूं जो प्रबंधक(manager) रिकॉर्ड है। इस तरह से एक के बाद एक इस सभी कार्यों को उपयुक्त कर्मचारी रिकॉर्ड के साथ उपयुक्त प्रकार के साथ बुलाया जाएगा और एक बार जब हम रिकॉर्ड के अंदर होंगे तो हम पहले ही देख चुके हैं कि अगर इंजीनियर(engineer) फ़ंक्शन(function) को आमंत्रित किया गया है और मुझे पॉइंटर(pointer) मिला है यहाँ इंजीनियर(engineer) रिकॉर्ड करने के लिए तो मैं कास्ट और निष्पादित करेंगे। यह ऐसा करने की मूल शैली है। हमने जो परिवर्तन किया है, वह है; हमने इस पूरी बात को फंक्शन(function) पॉइंटर्स(pointers) के एरे में बनाया है और हम उन्हें एक साधारण कोड के माध्यम से आमंत्रित कर रहे हैं। और हमें किसी भी स्विच की आवश्यकता नहीं है; सशर्त स्विच जो हम कर रहे थे वह सब इस फ़ंक्शन(function) पॉइंटर(pointer) सरणी में अनुक्रमण द्वारा ध्यान रखा गया है। यह C में एक और समाधान हो सकता है जो C में एक स्मार्ट समाधान है जो बहुत उपयोगी होगा। यदि हम जल्दी से इसे पॉलिमरिक C ++ समाधान के साथ तुलना करते हैं तो यह समाधान के लिए मूल दृष्टिकोण था। अगर आप गौर करेंगे तो आप देखेंगे कि हमारे पास विध्वंसक, निर्माणकर्ता, अलग-अलग ओवरराइड प्रक्रिया वेतन कार्यों और इसी तरह की सभी चीजें हैं। और इसके साथ ही अगर हम देखें, तो हमारा कोड केवल इस कॉल के साथ लूप के लिए है। जहां यह प्रत्येक और हर एक इंजीनियर(engineer) प्रकार के लिए एक संकेतक है और बहुलक प्रेषण के आधार पर यह उचित processSalary फ़ंक्शन(function) प्रक्रिया को कॉल करेगा। यदि हम इसे साइड बाइ साइड से तुलना करते हैं तो यह केवल डिज़ाइन सुविधाओं की तुलना कर रहा है। लेकिन अगर हम इसकी तुलना समाधान के साथ-साथ करते हैं तो आप देखेंगे कि यह C समाधान है, जो इसी C ++ क्लास(class) का है। तो, आपके पास इसमें इंजीनियर(engineer) है, आपके पास यहां कंस्ट्रक्टर है, आपके पास यह विशेष प्रसंस्करण फ़ंक्शन(function)(function) है, आपके पास ओवर लोड सदस्य(member) फ़ंक्शन(function)(function) है जो प्रकृति में एक पॉलीमोर्फिक(polymorphic) है। इसी तरह, मेरे पास अगले प्रकार के निर्देशक प्रकार हैं और ये तीन क्लास(class) हैं जो हमारे पास हैं। अब, यदि हम प्रसंस्करण भाग को देखते हैं, तो देखें कि यह दो प्रसंस्करण समान कैसे दिखते हैं। तो यहाँ मैं उस वस्तु को पॉइंटर(pointer) ले जाता हूँ और डायनामिक(dynamic) प्रकार के आधार पर मैं इसके संबंधित प्रकार के आधार पर इस किसी भी फंक्शन(function) को भेजता हूँ। यहाँ हम समान psArray का उपयोग करते हुए कार्य करते हैं जो कि फ़ंक्शन(function)(function) पॉइंटर्स(pointers) का सरणी है जिसका उपयोग किया जा सकता है। एकमात्र अंतर यह है कि मुझे स्पष्ट रूप से उस प्रकार और विशेष वस्तु के बीच के प्रकार और संबंध को बनाए रखने की जरूरत है जिसका मैं उपयोग कर रहा हूं। इसलिए मैं जिस प्रकार के फ़ंक्शन(function) को चुनता हूं उसके आधार पर और फिर उसके लिए विशेष रूप से दूसरा भाग बताता है कि ऑब्जेक्ट(object) पॉइंटर(pointer) क्या है और हम ऑब्जेक्ट(object) पॉइंटर(pointer) पास करते हैं। इसलिए, यहां मुझे ऐसा करने की आवश्यकता नहीं है क्योंकि जैसा कि हम सभी जानते हैं कि हमें मूल रूप से सही प्रकार चुनना है, ऑब्जेक्ट(object) पॉइंटर(pointer) इस सूचक के रूप में निहित है और यह काम करेगा। इसका कारण मैं आपको यह उदाहरण दिखाता हूं या इस तरह से आपको C में फ़ंक्शन(function) पॉइंटर(pointer) का उपयोग करते हुए दिखाता हूं, यह एक तथ्य है कि यह वास्तव में वास्तव में C ++ कंपाइलर वर्चुअल(virtual) फ़ंक्शन(function) या पॉलीमॉर्फिक(polymorphic) फ़ंक्शन(function) का ख्याल रखता है। इसलिए इसे वास्तविक विवरण में लाने के लिए, मान लीजिए कि मेरे पास एक बेस क्लास बी है, इसलिए इस बेस क्लास के लिए मेरे पास दो कार्य हैं; एक फ़ंक्शन(function) f है और यह फ़ंक्शन(function) जी। कौन से; एक पॉलिमरिक प्रकार का है, जी पॉलीमॉर्फिक प्रकार है, एफ एक गैर-पॉलीमॉर्फिक प्रकार है, यह एक गैर-वर्चुअल(virtual) कार्य है। और इस आधार क्लास(class) के आधार पर मेरे पास एक व्युत्पन्न क्लास(class) है जो गैर-पॉलीमोर्फिक(polymorphic) फ़ंक्शन(function) के साथ-साथ पॉलीमोर्फिक(polymorphic) फ़ंक्शन(function) भी लिखता है। अब, आप इस मामले में क्या करते हैं; एक गैर-पॉलीमोर्फिक(polymorphic) समारोह के लिए हमें यह कहना चाहिए कि यदि हम केवल उस कार्य f के बारे में बात करते हैं जो प्रकृति में गैर-पॉलीमोर्फिक(polymorphic) है, तो आह्वान कैसा दिखेगा? मान लीजिए अगर मैं नमूना बी.f () करता हूं जो सीधे ऑब्जेक्ट(object) के साथ इसे एक्सेस कर रहा है। तो, कंपाइलर इसे कैसे कहेंगे? कंपाइलर को इस तथ्य से पता चलेगा कि बी एक क्लास(class) बी प्रकार की वस्तु है जिसे कंपाइलर जानता है कि एक फ़ंक्शन(function)(function) एफ है जिससे इसे कहा जाता है। तो, यह बी कॉलन-कोलोन एफ कहता है जो कि यह कार्य है, और क्या आवश्यक है? इसके लिए इस सूचक की आवश्यकता होती है जो b का पता होता है, इसलिए यह b का पता डालता है और यह पैरामीटर डालता है। तो, यह यहाँ और पैरामीटर के ख का पता डालता है और यह कहा जाता है। यह एक स्थिर बंधन है; यह एक साधारण स्थैतिक बंधन है। अगर मैं एक पॉइंटर(pointer) का उपयोग कर रहा हूं तो मुझे एक पॉइंटर(pointer) के साथ ऐसा ही काम करना है। इसलिए, अगर मैं इसे कॉल कर रहा हूं, तो पॉइंटर(pointer) के प्रकार से जो कि बी टाइप का है, यह जानता है कि इसे उस बी क्लास में देखना है जिसे हमने पहले देखा है और बी क्लास में इसका फ़ंक्शन(function) f है जो कि गैर-वर्चुअल(virtual) है, तो यह सीधे उस फ़ंक्शन(function) को कॉल करना होगा। तो, यह सांख्यिकीय रूप से b :: f() सूचक मान और पैरामीटर को पास करता है। ये स्थिर तरीके हैं यह बिल्कुल ठीक है। अब, हम एक तीसरे आह्वान पर भी गौर करते हैं जहां मैं ऑब्जेक्ट(object) का उपयोग कर रहा हूं और गैर-वर्चुअल(virtual) फ़ंक्शन(function) जी को बुला रहा हूं। फिर से कंपाइलर वही काम करता है। हम जानते हैं कि यदि हम इसे वस्तु के साथ कहते हैं तो यह उस क्लास(class) का कार्य है जिसे कहा जाएगा, इसलिए b :: g () जिसे हम कहते हैं। बी का पता यहां से दिया गया है और पैरामीटर यहां से पारित किया गया है। तो, इन तीनों के लिए इस बिंदु तक ये सभी मूल रूप से स्थिर बंधन हैं। इसलिए, यदि मैं b के बजाय यदि मेरे पास एक व्युत्पन्न क्लास(class) वस्तु है d और मैं व्युत्पन्न क्लास(class) वस्तु के लिए ऐसा करने की कोशिश करता हूं तो मेरे पास समान स्थिर बाध्यकारी कोड होगा, जहां इनमें से प्रत्येक में संकलक जानता है कि प्रकार d है और चाहे वह ऑब्जेक्ट(object) द्वारा सीधे हो या यह एक पॉइंटर(pointer) के माध्यम से हो, लेकिन फ़ंक्शन(function) एक गैर वर्चुअल(virtual) है इसलिए यह स्थिर कॉल लगाएगा। समस्या तब उत्पन्न होती है जब मैं वास्तव में पी पॉइंटर(pointer) जी जैसी किसी चीज़ को कॉल करना चाहता हूं, अर्थात मैं एक कॉलिंग वर्चुअल(virtual) फ़ंक्शन(function) हूं और मैं एक पॉइंटर(pointer) का उपयोग कर रहा हूं, इसलिए यह वह जगह है जहां मुझे डायनेमिक बाइंडिंग(binding) की आवश्यकता है। मैं पी पॉइंटर(pointer) जी कह रहा हूं, मैं एक पॉइंटर(pointer) का उपयोग कर रहा हूं और मैं एक वर्चुअल(virtual) फ़ंक्शन(function) का उपयोग कर रहा हूं। इस मामले में p ऑब्जेक्ट(object) को एबट करने के लिए एक पॉइंटर(pointer) है, इस मामले में राइट हैंड साइड बी, डी ऑब्जेक्ट(object) के लिए पॉइंटर(pointer) है। तो, मुझे यहाँ क्या चाहिए? मुझे यहाँ इस बात की आवश्यकता होगी कि p यह कॉल वास्तव में इस फ़ंक्शन(function) को हल करेगा। जबकि मुझे इसकी आवश्यकता होगी कि इस मामले में यह कॉल इस फ़ंक्शन(function) को हल करेगा। भले ही कॉल साइट पर यह दोनों कॉल एक जैसे दिखते हों। मैं उसको कैसे करू? मैं वह परिवर्तन कैसे करूँ? इसलिए मैं जो कुछ करता हूं वह बहुत सरल है। ऑब्जेक्ट(object) के लेआउट के बारे में सोचें, ऑब्जेक्ट(object) में डेटा सदस्य(member) i है, इसलिए मेरे पास एक डेटा सदस्य(member) है I इसे सौ के साथ बनाया गया था। इसलिए, मेरे पास एक डेटा मेंबर I, b :: i है जो कि यहां का क्षेत्र है। इसी तरह, यदि मैं व्युत्पन्न क्लास(class) ऑब्जेक्ट(object) को देखता हूं, तो इसमें एक डेटा सदस्य(member) j जोड़ा गया है, इसलिए इसमें एक बेस क्लास हिस्सा होगा जो 200 है और अतिरिक्त डेटा सदस्य(member) जो 500 जोड़ा गया है। इसलिए ये ठीक हैं। अब हम क्या करते हैं हम एक और क्षेत्र जोड़ते हैं, यह अदृश्य क्षेत्र है जो हम ऑब्जेक्ट(object) में दायर एक और जोड़ते हैं। यह फ़ील्ड एक पॉइंटर(pointer) है और यह किस ओर इशारा करता है, यह फ़ंक्शन(function) पॉइंटर्स(pointers) की तालिका की ओर इशारा करता है और इस तालिका को वीएफटी या वर्चुअल(virtual) फंक्शन(function) टेबल(table) के रूप में जाना जाता है। तो यह क्या करता है, जब कहते हैं, मैं कक्षा बी में हूं और मैं कोड को देखने की कोशिश कर रहा हूं, मेरे पास एक वर्चुअल(virtual) फ़ंक्शन(function) पॉइंटर(pointer) है और मेरे पास एक वर्चुअल(virtual) फ़ंक्शन(function) है। तो मैंने इस तालिका में उस वर्चुअल(virtual) फ़ंक्शन(function) को रखा है जो मैंने इस सूचक को इस तालिका में रखा है। और जब भी मुझे इस फ़ंक्शन(function) के लिए कॉल आएगा इस वर्चुअल(virtual) फंक्शन(function) जी को एक पॉइंटर(pointer) के माध्यम से, मैं इस तरह एक कोड उत्पन्न नहीं करूंगा, मैं इस स्थिर कोड को उत्पन्न नहीं करूंगा बल्कि मैं इस तरह से एक कोड उत्पन्न करूंगा। इस वाक्य-विन्यास से भ्रमित न हों, क्या कहा जा रहा है? P एक पॉइंटर(pointer) है। तो p एक पॉइंटर(pointer) है, इसलिए p यहाँ पॉइंट करता है। P पॉइंटर(pointer) VFT क्या है? P पॉइंटर(pointer) VFT इस तालिका के लिए बताया गया है। और यदि p पॉइंटर(pointer) VFT को इस टेबल(table) की ओर इशारा किया जाए तो P पॉइंटर(pointer) VFT 0 इस तालिका की 0 वीं प्रविष्टि है, और वह प्रविष्टि क्या है? वह प्रविष्टि एक फ़ंक्शन(function) पॉइंटर(pointer) है। तो, p पॉइंटर(pointer) VFT 0 तालिका में यह 0 वां फ़ंक्शन(function) पॉइंटर(pointer) है। तो, मैं कहता हूं कि जब भी आपको p पॉइंटर(pointer) g मिलता है, तो आप वास्तव में इस स्थान पर जो भी फ़ंक्शन(function) होता है, उसे कॉल करते हैं। तो आप इस फ़ंक्शन(function) को चुनें और मापदंडों के साथ कॉल करें, इस पॉइंटर(pointer) के मापदंडों के साथ जो कि पी और वास्तविक पैरामीटर मान है जो 45 है। संकलक यह जानते हुए कि यह एक वर्चुअल(virtual) फ़ंक्शन(function) है और यह जानते हुए कि यह एक के माध्यम से बुलाया गया है पॉइंटर(pointer) स्टैटिक टाइम कोड को उत्पन्न नहीं करता है, जैसे कि फ़ंक्शन(function) को हार्ड कोड करता है, लेकिन यह कॉल को वर्चुअल(virtual) फ़ंक्शन(function) तालिका के माध्यम से रखता है। वह कैसे मदद करता है? जिस तरह से यह मदद करता है अब आपके पास दिशा में एक स्तर है। तो क्या होता है, जब आपने इस क्लास(class) बी को कक्षा डी में विशेषज्ञ किया है और आप उस वस्तु के लिए एक वस्तु का निर्माण करते हैं जिसमें एक वर्चुअल(virtual) फ़ंक्शन(function) तालिका सूचक भी होता है। वर्चुअल(virtual) फ़ंक्शन(function) तालिका की ओर इशारा करते हुए, यह तालिका अब कक्षा d की है, यह तालिका क्लास(class) b की थी। अब मैंने कक्षा d में क्या किया है? क्लास d में इस फंक्शन(function) वर्चुअल(virtual) फंक्शन(function) g को ओवरराइड किया गया है एक नई परिभाषा दी गई है जिससे अब d :: g हो गया है। इसलिए, जब हम विशेषज्ञता का पालन करते हैं, तो हम इस फ़ंक्शन(function) को b की वर्चुअल(virtual) फ़ंक्शन(function) तालिका से हटा देते हैं और ओवरराइडिंग के माध्यम से हम उस फ़ंक्शन(function) को डालते हैं जो हमने लिखा है कि वर्चुअल(virtual) फ़ंक्शन(function) तालिका में डी, डी-कोलोन-कोलोन जी के लिए एक फ़ंक्शन(function) है। और इस कॉल के लिए, कंपाइलर एक ही अप्रत्यक्ष कोड उत्पन्न करता है। अब क्या होगा? अब सोचना बंद। यह कॉल था और यही वह फंक्शन(function) है जिससे कंपाइलर जेनरेट होता है। इनसे कॉल होती है जो उत्पन्न हो रही है यही वह है जो स्टैटिक टाइम पैदा कर रहा है। अब क्या होता है, दो परिदृश्य हैं कि पी वास्तव में एब ऑब्जेक्ट(object) की ओर इशारा करता है। अगर यह एब ऑब्जेक्ट(object) को इंगित करता है तो इसमें वर्चुअल(virtual) फंक्शन(function) टेबल(table) पॉइंटर(pointer) है जो इसे b के इस वर्चुअल(virtual) फंक्शन(function) टेबल(table) पर जाता है जो इसे मिला है। यह फंक्शन(function) 0 के 0 वें फंक्शन(function) को चुनता है और कॉल करता है, इसलिए इसे b :: g कहते हैं। लेकिन यदि p यहाँ पर ad object की ओर इशारा कर रहा है तो इसमें एक अलग फंक्शन(function) पॉइंटर(pointer), वर्चुअल(virtual) फंक्शन(function) टेबल(table) पॉइंटर(pointer) है। जब यह उस पॉइंटर(pointer) वीपी पॉइंटर(pointer) VFT पर ट्रेस होता है तो यह वास्तव में d का वर्चुअल(virtual) फंक्शन(function) टेबल(table) प्राप्त करता है। यह 0 वें फंक्शन(function) को चुनता है जो कि यह फंक्शन(function) है, जो अब d :: g के साथ होता है क्योंकि यह वास्तव में एड ऑब्जेक्ट(object) को पॉइंट करता है इसलिए यह टेबल(table) अलग है। फिर यह मापदंडों को पास करता है और कॉल करता है कि स्वाभाविक रूप से डी :: जी को एक कहा जाएगा। इसके साथ, फ़ंक्शन(function) पॉइंटर(pointer) की तालिका का सरल तंत्र, इसलिए हम इस से क्या सीखेंगे, यदि कोई क्लास(class) पॉलीमोर्फिक(polymorphic) है यदि एक प्रकार पॉलीमोर्फिक(polymorphic) है यदि इसमें कम से कम एक वर्चुअल(virtual) फ़ंक्शन(function) है तो उस क्लास(class) के लिए एक वर्चुअल(virtual) फ़ंक्शन(function) होगा तालिका, जिसमें वे सभी वर्चुअल(virtual) फ़ंक्शंस होंगे, जिन्हें तालिका में एक के बाद एक उस क्रम में सूचीबद्ध किया गया है, जिसमें उन्हें परिभाषित किया गया है। यहां हमारे पास केवल एक प्रविष्टि है क्योंकि हमारे पास केवल एक वर्चुअल(virtual) फ़ंक्शन(function) है। यदि वहाँ अधिक हैं तो अधिक प्रविष्टियाँ होंगी और जैसे ही क्लास(class) विशेष होता है कंपाइलर चेक वर्चुअल(virtual) फ़ंक्शन(function) को क्लास(class) को फिर से परिभाषित करता है यदि वह ऐसा करता है तो वह अपनी वर्चुअल(virtual) फ़ंक्शन(function) तालिका में संबंधित प्रविष्टि को बदल देता है और उस संस्करण के साथ बदल देता है जिसमें ओवरराइड होता है। और फिर हमेशा सीधा कॉल करने के बजाय एक कॉल करता है जैसे कि यह एक स्टैटिक टाइप कॉल है जैसे यह जहां यह स्पष्ट रूप से कहता है कि फ़ंक्शन(function) क्या है, यह कहता है कि मुझे रनटाइम में फ़ंक्शन(function) के बारे में पता नहीं है तालिका 0 वां फ़ंक्शन(function) और जो भी फ़ंक्शन(function) पॉइंटर(pointer) है, वह आपका फ़ंक्शन(function) है। इसलिए, वर्चुअल(virtual) फ़ंक्शन(function) तालिका ऑब्जेक्ट(object) के प्रकार के आधार पर अलग-अलग होगी, लेकिन उसी तंत्र द्वारा इस फ़ंक्शन(function)(function) के लिए 0 वें स्थान में रनटाइम प्रविष्टि को उचित रूप से आधार क्लास(class) या फ़ंक्शन(function) में या तो फ़ंक्शन(function) के लिए एक बिंदु कहा जाएगा। व्युत्पन्न क्लास(class) में इस बात पर निर्भर करता है कि मेरे पास किस प्रकार की वस्तु है और इसलिए मैं किस प्रकार के वर्चुअल(virtual) फंक्शन(function) टेबल(table) की ओर इशारा कर रहा हूं। मूल वर्चुअल(virtual) फ़ंक्शन(function) मैं पॉइंटर(pointer) टेबल(table) तंत्र है जिसके द्वारा हम चीजें कर सकते हैं। जैसा कि मैंने कहा कि जब भी कोई क्लास(class) वर्चुअल(virtual) फ़ंक्शन(function)(function) को परिभाषित करता है तो एक छिपा हुआ सदस्य(member) चर क्लास(class) में जोड़ा जाता है जो यहाँ इंगित करता है। और रनटाइम के दौरान इनवोकेशन अप्रत्यक्ष रूप से इसके माध्यम से होता है और यह आरटीटीआई(RTTI) के नाम से जाना जाता है। हम RTTI के बारे में अधिक बात करेंगे जो पूरे पॉलीमॉर्फिक(polymorphic) सिस्टम की रन-टाइम टाइप सूचना है। यह एक और उदाहरण है, उदाहरण जिसे हमने एक बाध्यकारी अभ्यास के रूप में हल किया था ताकि आप यहां देख सकें कि यह आपके आगे के चित्रण के लिए है। यह मुख्य रूप से आपके अपने काम करने के लिए है, लेकिन हमारे पास एक क्लास(class) ए है और उससे विशिष्ट है कि हमारे पास क्लास(class) बी है, उससे विशिष्ट है कि हमारे पास क्लास(class) सी है। और कक्षा ए में एक पॉलीमोर्फिक(polymorphic) फ़ंक्शन(function) है, जिसमें एक वर्चुअल(virtual) कार्य होता है इसलिए स्वाभाविक रूप से पूरे पदानुक्रम(hierarchy) है पॉलीमोर्फिक(polymorphic) और इसलिए, इस पदानुक्रम(hierarchy) पर किसी भी क्लास(class) की सभी वस्तुओं पर एक वर्चुअल(virtual) फ़ंक्शन(function) टेबल(table) पॉइंटर(pointer) होगा। इसलिए यदि मेरे पास ऑब्जेक्ट(object) ए है, तो ऑब्जेक्ट(object) ए कहें, तो इसमें डेटा सदस्य(member) होंगे जो दिलचस्प नहीं हैं इसलिए हमने उन्हें सूचीबद्ध नहीं किया है, लेकिन इसमें एक वर्चुअल(virtual) फ़ंक्शन(function)(function) टेबल(table) पॉइंटर(pointer) होगा जो कक्षा ए के वीएफटी(VFT) को इंगित करेगा और कितने प्रविष्टियाँ होंगी? एक वर्चुअल(virtual) फंक्शन(function) f और एक वर्चुअल(virtual) फंक्शन(function) g है। तो वहाँ एक वर्चुअल(virtual) समारोह है वहाँ एक वर्चुअल(virtual) समारोह जी है। लेकिन जब यह बी करने में माहिर है तो आपने एच को भी एक वर्चुअल(virtual) कार्य किया है। तो क्या होगा? स्थान दो में एक तीसरा फ़ंक्शन(function)(function) जुड़ जाएगा। और 0 और 1 का क्या होगा? F को A में परिभाषित किया गया था और B के ऊपर सिर का नाम है। इसलिए, f के लिए 0 वीं प्रविष्टि छिपी हुई है। अब, एक कोलन-कोलोन f के स्थान पर आपके पास b :: f है। जी को एक वर्चुअल(virtual) फ़ंक्शन(function) के रूप में भी परिभाषित किया गया था क्योंकि यह स्थान एक में रहता है, लेकिन क्लास(class) बी ने जी को अधिलेखित नहीं किया है। इसलिए, जब आप विरासत में लेते हैं, तो आप वास्तव में फ़ंक्शन(function) नंबर एक के रूप में समान a :: g प्राप्त करते हैं। और h आपने इसे एक वर्चुअल(virtual) फंक्शन(function) बना दिया है इसलिए वर्चुअल(virtual) फंक्शन(function) टेबल(table) एक अतिरिक्त फंक्शन(function) पॉइंटर(pointer) के साथ जुड़ जाता है। जैसा कि आप सी वस्तु पर आते हैं कि आपने क्या किया है आपने जी को ओवरराइड किया है। तो, जो आपको मिलता है, आपने एफ के साथ कुछ भी नहीं किया है, इसलिए एफ बस विरासत में मिला है। तो आपको 0 वीं प्रविष्टि में b :: f मिला है, जो कि b- कोलोन-कोलोन f है। लेकिन यह एंट्री नंबर a :: g था, लेकिन अब आपके पास लिखा हुआ है, इसलिए यह c-colon-colon g के साथ लिखा जाता है। प्रवेश संख्या दो बी:: थी। क्लास बी में एच फ़ंक्शन(function) जो यहाँ पर लिखा गया है, इसलिए आपको सी :: एच मिलता है, यह है कि वर्चुअल(virtual) फ़ंक्शन(function) टेबल(table) कैसे बढ़ती रहेगी और यह मूल रूप से आपको बताएगा कि क्यों हमने कहा कि एक बार इस पदानुक्रम(hierarchy) पर वर्चुअल(virtual) हो जाता है वर्चुअल(virtual) बने रहना होगा क्योंकि एक बार यह कि संकलक बनाने के निर्णय के रूप में और यहाँ मैंने दिखाया है कि इस कोड के संकलन संस्करण क्या होंगे। तो आप यह कह सकते हैं कि यह वर्चुअल(virtual) फंक्शन(function) टेबल(table) एंट्री 0 पर जाता है, जी टेबल(table) एंट्री 1 में जाता है, लेकिन जहां मैं अगर पॉइंटर(pointer) एच करता हूं तो मेरे पास स्टैटिक बाइंडिंग(binding) है, स्पष्ट फ़ंक्शन(function)(function) कॉल करता है क्योंकि यह फ़ंक्शन(function)(function) गैर-वर्चुअल(virtual) था। जबकि जब मैं इसे pb के साथ करता हूं, तो यह क्लास b टाइप की ओर इशारा होता है, तब वे इसे वर्चुअल(virtual) फंक्शन(function) टेबल(table) के माध्यम से बाहर लाते हैं क्योंकि यहां क्लास b में वर्चुअल(virtual) फंक्शन(function) हो गया है। तो कृपया इस पर काम करें, कृपया इस निर्माण को बहुत ध्यान से समझने की कोशिश करें और इस स्रोत अभिव्यक्ति के माध्यम से काम करें और जहाँ आप स्थैतिक बाध्यकारी हैं और जहाँ आपके पास डायनामिक(dynamic) बंधन है, की संकलित अभिव्यक्ति के विरुद्ध, ताकि आप इसे भी समझ पाएँगे। कर्मचारियों के वेतन आवेदन के लिए इसका लाभ और अभिनव समाधान को संक्षेप में प्रस्तुत करने के लिए जो सी में फ़ंक्शन(function) पॉइंटर्स(pointers) का उपयोग करता है हमने यह बताने के लिए नींव रखी है कि वर्चुअल(virtual) फ़ंक्शन(function) पॉइंटर(pointer) टेबल(table) का उपयोग करके वर्चुअल(virtual) फ़ंक्शन(function) कैसे कार्यान्वित किए जाते हैं। कृपया इसे और अधिक स्पष्ट रूप से समझने की कोशिश करें ताकि डायनामिक(dynamic) प्रेषण के बारे में कोई भ्रम आपके दिमाग में स्पष्ट हो।