वर्चुअल मेथड टेबल: Difference between revisions

From Vigyanwiki
(Created page with "{{Short description|Mechanism for supporting dynamic dispatch}} {{redirect|Virtual table|virtual tables in SQL|View (SQL)}} {{Use dmy dates|date=January 2021}} कंप्...")
 
No edit summary
 
(5 intermediate revisions by 5 users not shown)
Line 1: Line 1:
{{Short description|Mechanism for supporting dynamic dispatch}}
{{Short description|Mechanism for supporting dynamic dispatch}}
{{redirect|Virtual table|virtual tables in SQL|View (SQL)}}
{{Use dmy dates|date=January 2021}}
{{Use dmy dates|date=January 2021}}


[[कंप्यूटर प्रोग्रामिंग]] में, एक वर्चुअल मेथड टेबल (VMT), [[ आभासी समारोह ]] टेबल, वर्चुअल कॉल टेबल, [[ प्रेषण तालिका ]], vtable, या vftable एक ऐसी प्रणाली है जिसका [[डी ([[प्रोग्रामिंग भाषा]])]] में [[गतिशील प्रेषण]] (या रन टाइम (प्रोग्राम जीवनचक्र चरण)) चलाने के लिए किया जाता है। -टाइम मेथड [[ नाम बंधन ]])।
कंप्यूटर प्रोग्रामिंग में, एक '''वर्चुअल मेथड टेबल (वीएमटी)''', [[ आभासी समारोह |वर्चुअल फलन]] टेबल, वर्चुअल कॉल टेबल, प्रेषण तालिका, वीटेबल, या वीएफटेबल एक ऐसी प्रणाली है जिसका डी ([[प्रोग्रामिंग भाषा]]) में [[गतिशील प्रेषण]] (या रन टाइम (प्रोग्राम जीवनचक्र चरण)) चलाने के लिए किया जाता है।


जब भी कोई [[ वर्ग (कंप्यूटर प्रोग्रामिंग) ]] एक वर्चुअल फ़ंक्शन (या [[ विधि (कंप्यूटर प्रोग्रामिंग) ]]) को परिभाषित करता है, तो अधिकांश [[ संकलक ]] क्लास में एक छिपे हुए [[सदस्य चर]] को जोड़ते हैं जो [[ सूचक (कंप्यूटर प्रोग्रामिंग) ]] की एक सरणी को (वर्चुअल) फ़ंक्शन को इंगित करता है जिसे वर्चुअल कहा जाता है। विधि तालिका। इन पॉइंटर्स का उपयोग रनटाइम पर उपयुक्त फ़ंक्शन कार्यान्वयनों को लागू करने के लिए किया जाता है, क्योंकि संकलन समय पर यह अभी तक ज्ञात नहीं हो सकता है कि बेस फ़ंक्शन को कॉल किया जाना है या किसी वर्ग द्वारा लागू किया गया एक व्युत्पन्न है जो आधार से वंशानुक्रम (ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग) है। कक्षा।
जब भी कोई [[ वर्ग (कंप्यूटर प्रोग्रामिंग) |वर्ग (कंप्यूटर प्रोग्रामिंग)]] एक वर्चुअल फलन (या[[ विधि (कंप्यूटर प्रोग्रामिंग) | विधि (कंप्यूटर प्रोग्रामिंग)]]) को परिभाषित करता है, तो अधिकांश [[ संकलक |पॉइंटर्स]] क्लास में एक छिपे हुए [[सदस्य चर|मेंबर वेरिएबल]] को जोड़ते हैं जो[[ सूचक (कंप्यूटर प्रोग्रामिंग) ]]की एक सरणी को (वर्चुअल) फलन को इंगित करता है जिसे वर्चुअल मेथड टेबल कहा जाता है। इन पॉइंटर्स का उपयोग रनटाइम पर उपयुक्त फलन कार्यान्वयनों को लागू करने के लिए किया जाता है, क्योंकि संकलन समय पर यह अभी तक ज्ञात नहीं हो सकता है कि बेस फलन को कॉल किया जाना है या किसी वर्ग द्वारा लागू किया गया एक व्युत्पन्न है जो आधार से वंशानुक्रम (ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग) है।


ऐसे डायनेमिक डिस्पैच को लागू करने के कई अलग-अलग तरीके हैं, लेकिन वर्चुअल मेथड टेबल का उपयोग विशेष रूप से [[C++]] और संबंधित भाषाओं (जैसे D (प्रोग्रामिंग लैंग्वेज) और C Sharp (प्रोग्रामिंग लैंग्वेज)|C#) के बीच आम है। [[ मूल दृश्य ]] और [[ डेल्फी (प्रोग्रामिंग भाषा) ]] जैसी भाषाएं जो कार्यान्वयन से वस्तुओं के प्रोग्रामेटिक इंटरफ़ेस को अलग करती हैं, वे भी इस दृष्टिकोण का उपयोग करती हैं, क्योंकि यह ऑब्जेक्ट को विधि पॉइंटर्स के एक अलग सेट का उपयोग करके एक अलग कार्यान्वयन का उपयोग करने की अनुमति देता है।
ऐसे डायनेमिक डिस्पैच को लागू करने के कई अलग-अलग तरीके हैं, लेकिन वर्चुअल मेथड टेबल का उपयोग विशेष रूप से [[C++]] और संबंधित भाषाओं (जैसे D (प्रोग्रामिंग लैंग्वेज) और C शार्प (प्रोग्रामिंग भाषा)) के बीच सामान्य है। [[ मूल दृश्य |विसुअल बेसिक]] और [[ डेल्फी (प्रोग्रामिंग भाषा) |डेल्फी (प्रोग्रामिंग भाषा)]] जैसी भाषाएं जो कार्यान्वयन से वस्तुओं के प्रोग्रामेटिक अंतरापृष्ठ को अलग करती हैं, वे भी इस दृष्टिकोण का उपयोग करती हैं, क्योंकि यह ऑब्जेक्ट को विधि पॉइंटर्स के एक अलग सम्मुच्चय का उपयोग करके एक अलग कार्यान्वयन का उपयोग करने की अनुमति देता है।


मान लीजिए कि एक कार्यक्रम में वंशानुक्रम पदानुक्रम में तीन वर्ग हैं: एक [[सुपरक्लास (कंप्यूटर विज्ञान)]], {{mono|Cat}}, और दो [[उपवर्ग (कंप्यूटर विज्ञान)]], {{mono|HouseCat}} और {{mono|Lion}}. कक्षा {{mono|Cat}} नाम के एक वर्चुअल फंक्शन को परिभाषित करता है {{mono|speak}}, इसलिए इसके उपवर्ग उचित कार्यान्वयन प्रदान कर सकते हैं (उदाहरण के लिए या तो {{mono|meow}} या {{mono|roar}}). जब कार्यक्रम कॉल करता है {{mono|speak}} पर कार्य करता है {{mono|Cat}} संदर्भ (जो एक उदाहरण को संदर्भित कर सकता है {{mono|Cat}}, या का एक उदाहरण {{mono|HouseCat}} या {{mono|Lion}}), कोड को यह निर्धारित करने में सक्षम होना चाहिए कि फ़ंक्शन के किस कार्यान्वयन को कॉल भेजा जाना चाहिए। यह वस्तु के वास्तविक वर्ग पर निर्भर करता है, न कि इसके संदर्भ के वर्ग पर ({{mono|Cat}}). वर्ग को आम तौर पर स्थिर रूप से निर्धारित नहीं किया जा सकता है (अर्थात [[संकलन समय]] पर), इसलिए न तो संकलक यह तय कर सकता है कि उस समय कौन सा फ़ंक्शन कॉल करना है। कॉल को गतिशील रूप से (यानी, रन टाइम (प्रोग्राम लाइफसाइकिल चरण) पर) सही फ़ंक्शन पर भेजा जाना चाहिए।
मान लीजिए कि एक कार्यक्रम में वंशानुक्रम पदानुक्रम में तीन वर्ग हैं: एक [[सुपरक्लास (कंप्यूटर विज्ञान)]], {{mono|Cat}}, और दो [[उपवर्ग (कंप्यूटर विज्ञान)]], {{mono|HouseCat}} और {{mono|Lion}}। वर्ग {{mono|Cat}} नाम के एक वर्चुअल फंक्शन को {{mono|speak}} परिभाषित करता है, इसलिए इसके उपवर्ग उचित कार्यान्वयन प्रदान कर सकते हैं (उदाहरण के लिए या तो {{mono|meow}} या {{mono|roar}})जब प्रोग्राम {{mono|Cat}} संदर्भ पर {{mono|speak}} फलन को कॉल करता है (जो {{mono|Cat}} के उदाहरण, या {{mono|HouseCat}} या {{mono|Lion}} के उदाहरण को संदर्भित कर सकता है), तो कोड यह निर्धारित करने में सक्षम होना चाहिए कि कॉल को फलन के किस कार्यान्वयन के लिए भेजा जाना चाहिए। यह वस्तु के वास्तविक वर्ग पर निर्भर करता है, न कि ({{mono|Cat}}) इसके संदर्भ के वर्ग पर निर्भर करता है। वर्ग को सामान्यतः स्थिर रूप से निर्धारित नहीं किया जा सकता है (अर्थात [[संकलन समय]] पर), इसलिए न तो संकलक यह तय कर सकता है कि उस समय कौन सा फलन कॉल करना है। कॉल को गतिशील रूप से (यानी, रन टाइम (प्रोग्राम लाइफसाइकिल चरण) पर) सही फलन पर भेजा जाना चाहिए।


== कार्यान्वयन ==
== कार्यान्वयन ==
<!-- [[Virtual function pointer]] redirects here -->
ऑब्जेक्ट की वर्चुअल विधि तालिका में ऑब्जेक्ट की गतिशील रूप से बाध्य विधियों का मेमोरी पता होगा है। ऑब्जेक्ट के वर्चुअल मेथड टेबल से मेथड का पता लाकर मेथड कॉल की जाती है। वर्चुअल विधि तालिका एक ही वर्ग से संबंधित सभी वस्तुओं के लिए समान होती है, और इसलिए सामान्यतः उनके बीच साझा की जाती है। प्रकार-संगत वर्गों से संबंधित वस्तुएं (उदाहरण के लिए वंशानुक्रम पदानुक्रम में सिब्लिंग्स) एक ही लेआउट के साथ वर्चुअल विधि तालिकाएँ होंगी: किसी दिए गए विधि का पता सभी प्रकार-संगत वर्गों के लिए समान अनुचित्रण पर दिखाई देगा। इस प्रकार, किसी दिए गए अनुचित्रण से वर्चुअल विधि तालिका में विधि का पता लाने से ऑब्जेक्ट की वास्तविक कक्षा से संबंधित विधि मिल जाएगी।<ref>Ellis & Stroustrup 1990, pp. 227–232</ref>
ऑब्जेक्ट की वर्चुअल विधि तालिका में ऑब्जेक्ट की गतिशील रूप से बाध्य विधियों का मेमोरी पता होगा। ऑब्जेक्ट के वर्चुअल मेथड टेबल से मेथड का पता लाकर मेथड कॉल की जाती है। वर्चुअल विधि तालिका एक ही वर्ग से संबंधित सभी वस्तुओं के लिए समान होती है, और इसलिए आमतौर पर उनके बीच साझा की जाती है। प्रकार-संगत वर्गों से संबंधित वस्तुएं (उदाहरण के लिए वंशानुक्रम पदानुक्रम में भाई-बहन) एक ही लेआउट के साथ आभासी विधि तालिकाएँ होंगी: किसी दिए गए विधि का पता सभी प्रकार-संगत वर्गों के लिए समान ऑफ़सेट पर दिखाई देगा। इस प्रकार, किसी दिए गए ऑफ़सेट से वर्चुअल विधि तालिका में विधि का पता लाने से ऑब्जेक्ट की वास्तविक कक्षा से संबंधित विधि मिल जाएगी।<ref>Ellis & Stroustrup 1990, pp. 227–232</ref>
सी ++ मानकों को अनिवार्य नहीं है कि गतिशील प्रेषण को कैसे कार्यान्वित किया जाना चाहिए, लेकिन कंपाइलर्स आम तौर पर एक ही मूल मॉडल पर मामूली बदलाव का उपयोग करते हैं।


आमतौर पर, कंपाइलर प्रत्येक वर्ग के लिए एक अलग वर्चुअल मेथड टेबल बनाता है। जब कोई ऑब्जेक्ट बनाया जाता है, तो इस तालिका में एक पॉइंटर, जिसे वर्चुअल टेबल पॉइंटर, vpointer या VPTR कहा जाता है, इस ऑब्जेक्ट के छिपे हुए सदस्य के रूप में जोड़ा जाता है। जैसे, कंपाइलर को प्रत्येक वर्ग के [[कंस्ट्रक्टर (ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग)]] में छिपे हुए कोड को भी उत्पन्न करना चाहिए ताकि एक नए ऑब्जेक्ट के वर्चुअल टेबल पॉइंटर को उसके क्लास के वर्चुअल मेथड टेबल के पते पर इनिशियलाइज़ किया जा सके।
C ++ मानकों को अनिवार्य नहीं है कि गतिशील प्रेषण को कैसे कार्यान्वित किया जाना चाहिए, लेकिन कंपाइलर्स सामान्यतः एक ही मूल प्रतिरूप पर सामान्य बदलाव का उपयोग करते हैं।


कई कंपाइलर वर्चुअल टेबल पॉइंटर को ऑब्जेक्ट के अंतिम सदस्य के रूप में रखते हैं; अन्य संकलक इसे पहले स्थान पर रखते हैं; पोर्टेबल स्रोत कोड किसी भी तरह से काम करता है।<ref>
सामान्यतः, कंपाइलर प्रत्येक वर्ग के लिए एक अलग वर्चुअल मेथड टेबल बनाता है। जब कोई ऑब्जेक्ट बनाया जाता है, तो इस तालिका में एक पॉइंटर, जिसे वर्चुअल टेबल पॉइंटर, वीपॉइंटर या वीपीटीआर कहा जाता है, इस ऑब्जेक्ट के छिपे हुए सदस्य के रूप में जोड़ा जाता है। जैसे, कंपाइलर को प्रत्येक वर्ग के [[कंस्ट्रक्टर (ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग)]] में छिपे हुए कोड को भी उत्पन्न करना चाहिए ताकि एक नए ऑब्जेक्ट के वर्चुअल टेबल पॉइंटर को उसके क्लास के वर्चुअल मेथड टेबल के पते पर आवाक्षरित किया जा सके।
 
कई कंपाइलर वर्चुअल टेबल पॉइंटर को ऑब्जेक्ट के अंतिम सदस्य के रूप में रखते हैं; अन्य संकलक इसे पहले स्थान पर रखते हैं; सुवाह्य स्रोत कोड किसी भी तरह से काम करता है।<ref>
Danny Kalev.
Danny Kalev.
[http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=196 "C++ Reference Guide: The Object Model II"].
[http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=196 "C++ Reference Guide: The Object Model II"].
Line 24: Line 23:
Heading "Inheritance and Polymorphism" and "Multiple Inheritance".
Heading "Inheritance and Polymorphism" and "Multiple Inheritance".
</ref>
</ref>
उदाहरण के लिए, [[g++]] ने पहले पॉइंटर को ऑब्जेक्ट के अंत में रखा था।<ref>{{cite web |url=http://www.codesourcery.com/public/cxx-abi/cxx-closed.html |title=सी ++ एबीआई बंद मुद्दे|access-date=2011-06-17 |url-status=bot: unknown |archive-url=https://web.archive.org/web/20110725153606/http://www.codesourcery.com/public/cxx-abi/cxx-closed.html |archive-date=25 July 2011}}</ref>
 
उदाहरण के लिए, [[g++]] ने पहले पॉइंटर को ऑब्जेक्ट के अंत में रखा था। <ref>{{cite web |url=http://www.codesourcery.com/public/cxx-abi/cxx-closed.html |title=सी ++ एबीआई बंद मुद्दे|access-date=2011-06-17 |url-status=bot: unknown |archive-url=https://web.archive.org/web/20110725153606/http://www.codesourcery.com/public/cxx-abi/cxx-closed.html |archive-date=25 July 2011}}</ref>
 




Line 59: Line 60:
D  *d  = new D();
D  *d  = new D();
</syntaxhighlight>
</syntaxhighlight>
जीएनयू कंपाइलर संग्रह से जी ++ 3.4.6 वस्तु के लिए निम्नलिखित 32-बिट मेमोरी लेआउट उत्पन्न करता है <code>b2</code>:<ref group="nb">G++'s <code>-fdump-class-hierarchy</code> (starting with version 8: <code>-fdump-lang-class</code>) argument can be used to dump virtual method tables for manual inspection. For AIX VisualAge XlC compiler, use <code>-qdump_class_hierarchy</code> to dump class hierarchy and virtual function table layout.</ref>
जीएनयू कंपाइलर संग्रह से जी ++ 3.4.6 वस्तु के लिए निम्नलिखित <code>b2</code>32-बिट मेमोरी लेआउट उत्पन्न करता है: <ref group="nb">G++'s <code>-fdump-class-hierarchy</code> (starting with version 8: <code>-fdump-lang-class</code>) argument can be used to dump virtual method tables for manual inspection. For AIX VisualAge XlC compiler, use <code>-qdump_class_hierarchy</code> to dump class hierarchy and virtual function table layout.</ref>
<पूर्व>
<पूर्व>
बी 2:
बी 2:
  +0: ​​बी 2 की वर्चुअल विधि तालिका के सूचक
  +4: int_in_b2 का मान


B2 की आभासी विधि तालिका:
B2 की वर्चुअल विधि तालिका:
   +0: ​​बी 2 :: एफ 2 ()
   b2:
</पूर्व>


  +0: pointer to virtual method table of B2
  +4: value of int_in_b2
virtual method table of B2:
  +0: B2::f2() 
और ऑब्जेक्ट के लिए निम्न मेमोरी लेआउट <code>d</code>:
और ऑब्जेक्ट के लिए निम्न मेमोरी लेआउट <code>d</code>:
<पूर्व>
डी:
  +0: ​​डी की वर्चुअल विधि तालिका के लिए सूचक (बी 1 के लिए)
  +4: int_in_b1 का मान
  +8: डी की आभासी विधि तालिका के सूचक (बी 2 के लिए)
+12: int_in_b2 का मान
+16: int_in_d का मान
कुल आकार: 20 बाइट्स।


D की आभासी विधि तालिका (B1 के लिए):
   d:
   +0: ​​बी 1 :: एफ 1 () // बी 1 :: एफ 1 () ओवरराइड नहीं है


D की आभासी विधि तालिका (B2 के लिए):
  +0: pointer to virtual method table of D (for B1)
   +0: ​​डी :: एफ 2 () // बी 2 :: एफ 2 () डी :: एफ 2 () द्वारा ओवरराइड किया गया है
  +4: value of int_in_b1
                // बी 2 :: एफ 2 का स्थान डी के लिए वर्चुअल विधि तालिका में नहीं है
  +8: pointer to virtual method table of D (for B2)
</पूर्व>
  +12: value of int_in_b2
   +16: value of int_in_d
Total size: 20 Bytes.
virtual method table of D (for B1):
  +0: B1::f1() // B1::f1() is not overridden
virtual method table of D (for B2):
  +0: D::f2()  // B2::f2() is overridden by D::f2()
                // The location of B2::f2 is not in the virtual method table for D
ध्यान दें कि वे कार्य <code>virtual</code>कीवर्ड नहीं ले रहे हैं उनकी घोषणा में (जैसे <code>fnonvirtual()</code> और <code>d()</code>) सामान्यतः वर्चुअल मेथड टेबल में दिखाई नहीं देते हैं।[[ डिफ़ॉल्ट कंस्ट्रक्टर | डिफ़ॉल्ट कंस्ट्रक्टर]] द्वारा उत्पन्न विशेष स्तिथियों के अपवाद हैं।


ध्यान दें कि वे कार्य कीवर्ड नहीं ले रहे हैं <code>virtual</code> उनकी घोषणा में (जैसे <code>fnonvirtual()</code> और <code>d()</code>) आमतौर पर वर्चुअल मेथड टेबल में दिखाई नहीं देते हैं। [[ डिफ़ॉल्ट कंस्ट्रक्टर ]] द्वारा उत्पन्न विशेष मामलों के अपवाद हैं।
वर्चुअल फलन में वर्चुअल डिस्ट्रक्टर्स <code>B1</code> और <code>B2</code>पर भी ध्यान दें। उन्हें सुनिश्चित करना आवश्यक है <code>delete d</code> न केवल स्मृति <code>D</code>को मुक्त कर सकते हैं, बल्कि <code>B1</code> और <code>B2</code> के लिए भी मुक्त कर सकते हैं, अगर <code>d</code> एक सूचक या प्रकार का संदर्भ <code>B1</code> या <code>B2</code> है। उदाहरण को सरल रखने के लिए उन्हें मेमोरी लेआउट से बाहर रखा गया था। <ref group="nb">{{Cite web|url=https://stackoverflow.com/questions/17960917/why-there-are-two-virtual-destructor-in-the-virtual-table-and-where-is-address-o|title = C++ - why there are two virtual destructor in the virtual table and where is address of the non-virtual function (gcc4.6.3)}}</ref>


वर्चुअल फ़ंक्शन # बेस क्लास में वर्चुअल डिस्ट्रक्टर्स पर भी ध्यान दें, <code>B1</code> और <code>B2</code>. उन्हें सुनिश्चित करना आवश्यक है <code>delete d</code> न केवल स्मृति को मुक्त कर सकते हैं <code>D</code>, बल्कि इसके लिए भी <code>B1</code> और <code>B2</code>, अगर <code>d</code> एक सूचक या प्रकार का संदर्भ है <code>B1</code> या <code>B2</code>. उदाहरण को सरल रखने के लिए उन्हें मेमोरी लेआउट से बाहर रखा गया था। <ref group="nb">{{Cite web|url=https://stackoverflow.com/questions/17960917/why-there-are-two-virtual-destructor-in-the-virtual-table-and-where-is-address-o|title = C++ - why there are two virtual destructor in the virtual table and where is address of the non-virtual function (gcc4.6.3)}}</ref>
[[ओवरराइडिंग विधि]] <code>f2()</code> कक्षा में <code>D</code> की वर्चुअल विधि तालिका को प्रतिलिपि करके कार्यान्वित किया जाता है और <code>B2</code>सूचक की जगह <code>B2::f2()</code> एक सूचक <code>D::f2()</code> के साथ है।
[[ओवरराइडिंग विधि]] <code>f2()</code> कक्षा में <code>D</code> की वर्चुअल विधि तालिका को डुप्लिकेट करके कार्यान्वित किया जाता है <code>B2</code> और सूचक की जगह <code>B2::f2()</code> एक सूचक के साथ <code>D::f2()</code>.


== [[एकाधिक वंशानुक्रम]] और थंक्स ==
== [[एकाधिक वंशानुक्रम]] और थंक्स ==
जी ++ कंपाइलर कक्षाओं की एकाधिक विरासत को लागू करता है <code>B1</code> और <code>B2</code> कक्षा में <code>D</code> दो वर्चुअल मेथड टेबल का उपयोग करना, प्रत्येक बेस क्लास के लिए एक। (मल्टीपल इनहेरिटेंस को लागू करने के अन्य तरीके हैं, लेकिन यह सबसे आम है।) यह पॉइंटर फिक्सअप की आवश्यकता की ओर ले जाता है, जिसे [[थंक (प्रोग्रामिंग)]] भी कहा जाता है, जब टाइप रूपांतरण होता है।
G++ कंपाइलर प्रत्येक बेस क्लास के लिए दो वर्चुअल मेथड टेबल का उपयोग करके क्लास <code>D</code> में क्लास <code>B1</code>और <code>B2</code> के विविध इनहेरिटेंस को लागू करता है। (विविध इनहेरिटेंस को लागू करने के अन्य तरीके हैं, लेकिन यह सबसे सामान्य है।) यह पॉइंटर फिक्सअप की आवश्यकता की ओर ले जाता है, जिसे [[थंक (प्रोग्रामिंग)]] भी कहा जाता है, जब टाइप रूपांतरण होता है।


निम्नलिखित सी ++ कोड पर विचार करें:
निम्नलिखित सी ++ कोड पर विचार करें:
Line 102: Line 105:
B2 *b2 = d;
B2 *b2 = d;
</syntaxhighlight>
</syntaxhighlight>
जबकि <code>d</code> और <code>b1</code> इस कोड के निष्पादन के बाद उसी स्मृति स्थान को इंगित करेगा, <code>b2</code> स्थान की ओर संकेत करेगा <code>d+8</code> (आठ बाइट्स की स्मृति स्थान से परे <code>d</code>). इस प्रकार, <code>b2</code> भीतर के क्षेत्र की ओर इशारा करता है <code>d</code> का एक उदाहरण लगता है <code>B2</code>, यानी, एक उदाहरण के रूप में एक ही मेमोरी लेआउट है <code>B2</code>.
जबकि <code>d</code> और <code>b1</code> इस कोड के निष्पादन के बाद उसी स्मृति स्थान को इंगित करेगा, <code>b2</code> स्थान की ओर संकेत करेगा <code>d+8</code> (आठ बाइट्स की स्मृति स्थान से परे <code>d</code>)इस प्रकार, <code>b2</code> भीतर के क्षेत्र की ओर इशारा करता है <code>d</code> का एक उदाहरण <code>B2</code> लगता है, यानी, एक उदाहरण के रूप में एक ही मेमोरी लेआउट <code>B2</code> है।
 
== मंगलाचरण ==
को एक कॉल <code>d->f1()</code> dereferencing द्वारा नियंत्रित किया जाता है <code>d</code>'एस <code>D::B1</code> vpointer, ऊपर देख रहा है <code>f1</code> वर्चुअल मेथड टेबल में एंट्री, और फिर कोड को कॉल करने के लिए उस पॉइंटर को डिफ्रेंस करना।


एकल वंशानुक्रम
== आघोष ==
<code>d->f1()</code>को एक कॉल अपसंदर्भन द्वारा नियंत्रित किया जाता है <code>d</code>'एस <code>D::B1</code> वीपॉइंटर, ऊपर <code>f1</code>देख रहा है।  वर्चुअल मेथड टेबल में एंट्री, और फिर कोड को कॉल करने के लिए उस पॉइंटर को अपसंदर्भन करना है।


एकल वंशानुक्रम (या केवल एकल वंशानुक्रम वाली भाषा में) के मामले में, यदि vpointer हमेशा पहला तत्व होता है <code>d</code> (जैसा कि यह कई कंपाइलर्स के साथ है), यह निम्न छद्म-सी ++ को कम करता है:
==== एकल वंशानुक्रम ====
एकल वंशानुक्रम (या केवल एकल वंशानुक्रम वाली भाषा में) की स्तिथि में, यदि वीपॉइंटर हमेशा पहला तत्व <code>d</code> होता है (जैसा कि यह कई कंपाइलर्स के साथ है), यह निम्न छद्म-C ++ को कम करता है:


<syntaxhighlight lang="cpp">
<syntaxhighlight lang="cpp">
(*((*d)[0]))(d)
(*((*d)[0]))(d)
</syntaxhighlight>
</syntaxhighlight>
कहाँ <code>*d</code> की आभासी विधि तालिका को संदर्भित करता है <code>D</code> और <code>[0]</code> वर्चुअल विधि तालिका में पहली विधि को संदर्भित करता है। पैरामीटर <code>d</code> यह (कंप्यूटर विज्ञान) बन जाता है |<code>this</code>वस्तु के लिए सूचक।
जहाँ <code>*d</code> की वर्चुअल विधि तालिका को संदर्भित करता है, <code>D</code> और <code>[0]</code> वर्चुअल विधि तालिका में पहली विधि को संदर्भित करता है। मापदण्ड <code>d</code> यह (कंप्यूटर विज्ञान) बन जाता है |<code>this</code>वस्तु के लिए सूचक है।


एकाधिक वंशानुक्रम
==== एकाधिक वंशानुक्रम ====
 
अधिक सामान्य स्तिथि में, कॉलिंग <code>B1::f1()</code> या <code>D::f2()</code> अधिक जटिल है:
अधिक सामान्य मामले में, कॉलिंग <code>B1::f1()</code> या <code>D::f2()</code> अधिक जटिल है:


<syntaxhighlight lang="cpp">
<syntaxhighlight lang="cpp">
Line 124: Line 125:
(*(*(d[+8]/*pointer to virtual method table of D (for B2)*/)[0]))(d+8) /* Call d->f2() */
(*(*(d[+8]/*pointer to virtual method table of D (for B2)*/)[0]))(d+8) /* Call d->f2() */
</syntaxhighlight>
</syntaxhighlight>
को कॉल <code>d->f1()</code> ए पास करता है <code>B1</code> एक पैरामीटर के रूप में सूचक। को कॉल <code>d->f2()</code> ए पास करता है <code>B2</code> एक पैरामीटर के रूप में सूचक। इस दूसरी कॉल के लिए सही पॉइंटर बनाने के लिए फिक्सअप की आवश्यकता होती है। के स्थान <code>B2::f2</code> के लिए वर्चुअल मेथड टेबल में नहीं है <code>D</code>.
<code>d->f1()</code>पर कॉल एक मापदण्ड के रूप में <code>B1</code> पॉइंटर को पास करती है। <code>d->f2()</code> पर कॉल एक मापदण्ड के रूप में <code>B2</code> पॉइंटर को पास करती है। इस दूसरी कॉल के लिए सही पॉइंटर उत्पन्न करने के लिए फ़िक्सअप की आवश्यकता होती है। <code>B2::f2</code> का स्थान <code>D</code> के लिए वर्चुअल विधि तालिका में नहीं है।


तुलना करके, एक कॉल करने के लिए <code>d->fnonvirtual()</code> ज्यादा सरल है:
तुलनात्मक रूप से, <code>d->fnonvirtual()</code> पर कॉल करना बहुत आसान है:


<syntaxhighlight lang="cpp">
<syntaxhighlight lang="cpp">
Line 134: Line 135:


== दक्षता ==
== दक्षता ==
एक गैर-वर्चुअल कॉल की तुलना में एक वर्चुअल कॉल के लिए कम से कम एक अतिरिक्त अनुक्रमित डीरेफरेंस और कभी-कभी एक फिक्सअप जोड़ की आवश्यकता होती है, जो केवल संकलित-इन पॉइंटर के लिए एक छलांग है। इसलिए, वर्चुअल फ़ंक्शंस को कॉल करना गैर-वर्चुअल फ़ंक्शंस को कॉल करने की तुलना में स्वाभाविक रूप से धीमा है। 1996 में किए गए एक प्रयोग से संकेत मिलता है कि निष्पादन समय का लगभग 6-13% केवल सही कार्य को भेजने में व्यतीत होता है, हालांकि ओवरहेड 50% जितना अधिक हो सकता है।<ref>Driesen, Karel and Hölzle, Urs, [https://dl.acm.org/doi/10.1145/236338.236369 "The Direct Cost of Virtual Function Calls in C++"], OOPSLA 1996</ref> आधुनिक कार्यों पर आभासी कार्यों की लागत इतनी अधिक नहीं हो सकती है {{abbr|CPU|Central Processing Unit}} बहुत बड़े कैश और बेहतर [[ शाखा भविष्यवक्ता ]] के कारण आर्किटेक्चर।
एक गैर-वर्चुअल कॉल की तुलना में एक वर्चुअल कॉल के लिए कम से कम एक अतिरिक्त अनुक्रमित डीरेफरेंस और कभी-कभी एक फिक्सअप जोड़ की आवश्यकता होती है, जो केवल संकलित-इन पॉइंटर के लिए एक विषयांतर है। इसलिए, वर्चुअल फलन को कॉल करना गैर-वर्चुअल फलन को कॉल करने की तुलना में स्वाभाविक रूप से धीमा है। 1996 में किए गए एक प्रयोग से संकेत मिलता है कि निष्पादन समय का लगभग 6-13% केवल सही कार्य को भेजने में व्यतीत होता है, हालांकि शिरोपरि 50% जितना अधिक हो सकता है। <ref>Driesen, Karel and Hölzle, Urs, [https://dl.acm.org/doi/10.1145/236338.236369 "The Direct Cost of Virtual Function Calls in C++"], OOPSLA 1996</ref> आधुनिक कार्यों पर वर्चुअल कार्यों {{abbr|सीपीयू|सेंट्रल प्रोसेसिंग यूनिट}} की लागत इतनी अधिक नहीं हो सकती है, बहुत बड़े कैश और बेहतर [[ शाखा भविष्यवक्ता |ब्रांच प्रेडिक्शन]] के कारण आर्किटेक्चर है।


इसके अलावा, ऐसे वातावरण में जहां [[समय-समय पर संकलन]] उपयोग में नहीं है, वर्चुअल फ़ंक्शन कॉल आमतौर पर [[इनलाइन विस्तार]] नहीं हो सकते हैं। कुछ मामलों में संकलक के लिए यह संभव हो सकता है कि वह डिवर्चुअलाइज़ेशन के रूप में जानी जाने वाली प्रक्रिया को अंजाम दे, जिसमें उदाहरण के लिए, लुकअप और अप्रत्यक्ष कॉल को प्रत्येक इनलाइन बॉडी के सशर्त निष्पादन के साथ बदल दिया जाता है, लेकिन ऐसे अनुकूलन सामान्य नहीं हैं।
इसके अतिरिक्त, ऐसे वातावरण में जहां [[समय-समय पर संकलन]] उपयोग में नहीं है, वर्चुअल फलन कॉल सामान्यतः [[इनलाइन विस्तार]] नहीं हो सकते हैं। कुछ स्तिथियों में संकलक के लिए यह संभव हो सकता है कि वह डिवर्चुअलाइज़ेशन के रूप में जानी जाने वाली प्रक्रिया को अंजाम दे, जिसमें उदाहरण के लिए, लुकअप और अप्रत्यक्ष कॉल को प्रत्येक इनलाइन बॉडी के सशर्त निष्पादन के साथ बदल दिया जाता है, लेकिन ऐसे अनुकूलन सामान्य नहीं हैं।


इस ओवरहेड से बचने के लिए, जब भी संकलन समय पर कॉल को हल किया जा सकता है, तो कंपाइलर आमतौर पर वर्चुअल मेथड टेबल का उपयोग करने से बचते हैं।
इस शिरोपरि से बचने के लिए, जब भी संकलन समय पर कॉल को हल किया जा सकता है, तो कंपाइलर सामान्यतः वर्चुअल मेथड टेबल का उपयोग करने से बचते हैं।


इस प्रकार, को कॉल करें <code>f1</code> उपरोक्त को टेबल लुकअप की आवश्यकता नहीं हो सकती है क्योंकि संकलक यह बताने में सक्षम हो सकता है <code>d</code> ए ही रख सकता है <code>D</code> इस बिंदु पर, और <code>D</code> ओवरराइड नहीं करता <code>f1</code>. या संकलक (या अनुकूलक) यह पता लगाने में सक्षम हो सकता है कि इसका कोई उपवर्ग नहीं है <code>B1</code> ओवरराइड करने वाले प्रोग्राम में कहीं भी <code>f1</code>. को कॉल <code>B1::f1</code> या <code>B2::f2</code> शायद टेबल लुकअप की आवश्यकता नहीं होगी क्योंकि कार्यान्वयन स्पष्ट रूप से निर्दिष्ट है (हालांकि इसे अभी भी 'इस'-पॉइंटर फिक्सअप की आवश्यकता है)।
इस प्रकार, उपरोक्त f1 पर कॉल के लिए तालिका लुकअप की आवश्यकता नहीं हो सकती है क्योंकि कंपाइलर यह बताने में सक्षम हो सकता है कि d केवल इस बिंदु पर D को पकड़ सकता है, और D, f1 को ओवरराइड नहीं करता है। या कंपाइलर (या ऑप्टिमाइज़र) यह पता लगाने में सक्षम हो सकता है कि प्रोग्राम में कहीं भी <code>B1</code> का कोई उपवर्ग नहीं है जो <code>f1</code> को ओवरराइड करता हो। <code>B1::f1</code> या <code>B2::f2</code> पर कॉल के लिए संभवतः तालिका लुकअप की आवश्यकता नहीं होगी क्योंकि कार्यान्वयन स्पष्ट रूप से निर्दिष्ट है (हालांकि इसे अभी भी 'यह'-पॉइंटर फ़िक्सअप की आवश्यकता है)।


== विकल्पों के साथ तुलना ==
== विकल्पों के साथ तुलना ==
डायनेमिक डिस्पैच प्राप्त करने के लिए वर्चुअल मेथड टेबल आमतौर पर एक अच्छा प्रदर्शन ट्रेड-ऑफ है, लेकिन उच्च प्रदर्शन के साथ [[बाइनरी ट्री डिस्पैच]] जैसे विकल्प हैं, लेकिन अलग-अलग लागतें हैं।<ref>Zendra, Olivier and Driesen, Karel, [http://www.usenix.org/event/jvm02/full_papers/zendra/zendra_html/index.html "Stress-testing Control Structures for Dynamic Dispatch in Java"], pp. 105–118, Proceedings of the USENIX 2nd Java Virtual Machine Research and Technology Symposium, 2002 (JVM '02)</ref>
डायनेमिक डिस्पैच प्राप्त करने के लिए वर्चुअल मेथड टेबल सामान्यतः एक अच्छा प्रदर्शन ट्रेड-ऑफ है, लेकिन उच्च प्रदर्शन के साथ [[बाइनरी ट्री डिस्पैच]] जैसे विकल्प हैं, लेकिन अलग-अलग लागतें हैं। <ref>Zendra, Olivier and Driesen, Karel, [http://www.usenix.org/event/jvm02/full_papers/zendra/zendra_html/index.html "Stress-testing Control Structures for Dynamic Dispatch in Java"], pp. 105–118, Proceedings of the USENIX 2nd Java Virtual Machine Research and Technology Symposium, 2002 (JVM '02)</ref> हालाँकि, वर्चुअल मेथड टेबल केवल विशेष मापदण्ड पर [[ एकल प्रेषण |एकल प्रेषण]] की अनुमति देते हैं, [[ एकाधिक प्रेषण |एकाधिक प्रेषण]] ([[कॉमन लिस्प ऑब्जेक्ट सिस्टम]], [[ डायलन (प्रोग्रामिंग भाषा)]], या [[ जूलिया (प्रोग्रामिंग भाषा) | जूलिया (प्रोग्रामिंग भाषा)]]) के विपरीत, जहां सभी प्रकार के मापदण्ड हो सकते हैं भेजने में ध्यान में रखा जाना चाहिए।
हालाँकि, वर्चुअल मेथड टेबल केवल विशेष पैरामीटर पर [[ एकल प्रेषण ]] की अनुमति देते हैं, [[ एकाधिक प्रेषण ]] ([[कॉमन लिस्प ऑब्जेक्ट सिस्टम]], [[ डायलन (प्रोग्रामिंग भाषा) ]], या [[ जूलिया (प्रोग्रामिंग भाषा) ]]) के विपरीत, जहां सभी प्रकार के पैरामीटर हो सकते हैं भेजने में ध्यान में रखा जाना चाहिए।


वर्चुअल मेथड टेबल भी तभी काम करते हैं जब डिस्पैचिंग विधियों के ज्ञात सेट तक सीमित हो, इसलिए उन्हें [[ बतख टाइपिंग ]] लैंग्वेज (जैसे स्मॉलटाक, पायथन (प्रोग्रामिंग लैंग्वेज) या [[जावास्क्रिप्ट]]) के विपरीत संकलन समय पर निर्मित एक साधारण सरणी में रखा जा सकता है। .
वर्चुअल मेथड टेबल भी तभी काम करते हैं जब डिस्पैचिंग विधियों के ज्ञात सम्मुच्चय तक सीमित हो, इसलिए उन्हें [[ बतख टाइपिंग |डक टाइपिंग]] लैंग्वेज (जैसे स्मॉलटाक, पायथन (प्रोग्रामिंग लैंग्वेज) या [[जावास्क्रिप्ट]]) के विपरीत संकलन समय पर निर्मित एक साधारण सरणी में रखा जा सकता है।


ऐसी भाषाएँ जो इनमें से कोई एक या दोनों सुविधाएँ प्रदान करती हैं, अक्सर [[हैश तालिका]] में एक स्ट्रिंग या किसी अन्य समकक्ष विधि को देखकर प्रेषित होती हैं। इसे तेज़ बनाने के लिए कई तरह की तकनीकें हैं (उदाहरण के लिए, [[स्ट्रिंग इंटर्निंग]]/टोकनिंग विधि नाम, कैशिंग लुकअप, समय-समय पर संकलन)।
ऐसी भाषाएँ जो इनमें से कोई एक या दोनों सुविधाएँ प्रदान करती हैं, प्रायः [[हैश तालिका]] में एक स्ट्रिंग या किसी अन्य समकक्ष विधि को देखकर प्रेषित होती हैं। इसे तेज़ बनाने के लिए कई तरह की तकनीकें हैं (उदाहरण के लिए, [[स्ट्रिंग इंटर्निंग]]/टोकनिंग विधि नाम, कैशिंग लुकअप, समय-समय पर संकलन)।


== यह भी देखें ==
== यह भी देखें ==
* आभासी कार्य
* वर्चुअल कार्य
*[[आभासी विरासत]]
*[[आभासी विरासत|वर्चुअल विरासत]]
* [[शाखा तालिका]]
* [[शाखा तालिका]]


Line 163: Line 163:
{{Reflist}}
{{Reflist}}


{{Application binary interface}}
{{DEFAULTSORT:Virtual Method Table}}
 
{{DEFAULTSORT:Virtual Method Table}}[[Category: विधि (कंप्यूटर प्रोग्रामिंग)]] [[Category: C++ कोड उदाहरण के साथ लेख]]
 
 


[[Category: Machine Translated Page]]
[[Category:Articles with hatnote templates targeting a nonexistent page|Virtual Method Table]]
[[Category:Created On 14/06/2023]]
[[Category:C++ कोड उदाहरण के साथ लेख|Virtual Method Table]]
[[Category:CS1 maint]]
[[Category:Collapse templates|Virtual Method Table]]
[[Category:Created On 14/06/2023|Virtual Method Table]]
[[Category:Lua-based templates|Virtual Method Table]]
[[Category:Machine Translated Page|Virtual Method Table]]
[[Category:Missing redirects|Virtual Method Table]]
[[Category:Navigational boxes| ]]
[[Category:Navigational boxes without horizontal lists|Virtual Method Table]]
[[Category:Pages with script errors|Virtual Method Table]]
[[Category:Sidebars with styles needing conversion|Virtual Method Table]]
[[Category:Template documentation pages|Documentation/doc]]
[[Category:Templates Vigyan Ready|Virtual Method Table]]
[[Category:Templates generating microformats|Virtual Method Table]]
[[Category:Templates that add a tracking category|Virtual Method Table]]
[[Category:Templates that are not mobile friendly|Virtual Method Table]]
[[Category:Templates that generate short descriptions|Virtual Method Table]]
[[Category:Templates using TemplateData|Virtual Method Table]]
[[Category:Use dmy dates from January 2021|Virtual Method Table]]
[[Category:Wikipedia metatemplates|Virtual Method Table]]
[[Category:विधि (कंप्यूटर प्रोग्रामिंग)|Virtual Method Table]]

Latest revision as of 16:38, 8 September 2023

कंप्यूटर प्रोग्रामिंग में, एक वर्चुअल मेथड टेबल (वीएमटी), वर्चुअल फलन टेबल, वर्चुअल कॉल टेबल, प्रेषण तालिका, वीटेबल, या वीएफटेबल एक ऐसी प्रणाली है जिसका डी (प्रोग्रामिंग भाषा) में गतिशील प्रेषण (या रन टाइम (प्रोग्राम जीवनचक्र चरण)) चलाने के लिए किया जाता है।

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

ऐसे डायनेमिक डिस्पैच को लागू करने के कई अलग-अलग तरीके हैं, लेकिन वर्चुअल मेथड टेबल का उपयोग विशेष रूप से C++ और संबंधित भाषाओं (जैसे D (प्रोग्रामिंग लैंग्वेज) और C शार्प (प्रोग्रामिंग भाषा)) के बीच सामान्य है। विसुअल बेसिक और डेल्फी (प्रोग्रामिंग भाषा) जैसी भाषाएं जो कार्यान्वयन से वस्तुओं के प्रोग्रामेटिक अंतरापृष्ठ को अलग करती हैं, वे भी इस दृष्टिकोण का उपयोग करती हैं, क्योंकि यह ऑब्जेक्ट को विधि पॉइंटर्स के एक अलग सम्मुच्चय का उपयोग करके एक अलग कार्यान्वयन का उपयोग करने की अनुमति देता है।

मान लीजिए कि एक कार्यक्रम में वंशानुक्रम पदानुक्रम में तीन वर्ग हैं: एक सुपरक्लास (कंप्यूटर विज्ञान), Cat, और दो उपवर्ग (कंप्यूटर विज्ञान), HouseCat और Lion। वर्ग Cat नाम के एक वर्चुअल फंक्शन को speak परिभाषित करता है, इसलिए इसके उपवर्ग उचित कार्यान्वयन प्रदान कर सकते हैं (उदाहरण के लिए या तो meow या roar)। जब प्रोग्राम Cat संदर्भ पर speak फलन को कॉल करता है (जो Cat के उदाहरण, या HouseCat या Lion के उदाहरण को संदर्भित कर सकता है), तो कोड यह निर्धारित करने में सक्षम होना चाहिए कि कॉल को फलन के किस कार्यान्वयन के लिए भेजा जाना चाहिए। यह वस्तु के वास्तविक वर्ग पर निर्भर करता है, न कि (Cat) इसके संदर्भ के वर्ग पर निर्भर करता है। वर्ग को सामान्यतः स्थिर रूप से निर्धारित नहीं किया जा सकता है (अर्थात संकलन समय पर), इसलिए न तो संकलक यह तय कर सकता है कि उस समय कौन सा फलन कॉल करना है। कॉल को गतिशील रूप से (यानी, रन टाइम (प्रोग्राम लाइफसाइकिल चरण) पर) सही फलन पर भेजा जाना चाहिए।

कार्यान्वयन

ऑब्जेक्ट की वर्चुअल विधि तालिका में ऑब्जेक्ट की गतिशील रूप से बाध्य विधियों का मेमोरी पता होगा है। ऑब्जेक्ट के वर्चुअल मेथड टेबल से मेथड का पता लाकर मेथड कॉल की जाती है। वर्चुअल विधि तालिका एक ही वर्ग से संबंधित सभी वस्तुओं के लिए समान होती है, और इसलिए सामान्यतः उनके बीच साझा की जाती है। प्रकार-संगत वर्गों से संबंधित वस्तुएं (उदाहरण के लिए वंशानुक्रम पदानुक्रम में सिब्लिंग्स) एक ही लेआउट के साथ वर्चुअल विधि तालिकाएँ होंगी: किसी दिए गए विधि का पता सभी प्रकार-संगत वर्गों के लिए समान अनुचित्रण पर दिखाई देगा। इस प्रकार, किसी दिए गए अनुचित्रण से वर्चुअल विधि तालिका में विधि का पता लाने से ऑब्जेक्ट की वास्तविक कक्षा से संबंधित विधि मिल जाएगी।[1]

C ++ मानकों को अनिवार्य नहीं है कि गतिशील प्रेषण को कैसे कार्यान्वित किया जाना चाहिए, लेकिन कंपाइलर्स सामान्यतः एक ही मूल प्रतिरूप पर सामान्य बदलाव का उपयोग करते हैं।

सामान्यतः, कंपाइलर प्रत्येक वर्ग के लिए एक अलग वर्चुअल मेथड टेबल बनाता है। जब कोई ऑब्जेक्ट बनाया जाता है, तो इस तालिका में एक पॉइंटर, जिसे वर्चुअल टेबल पॉइंटर, वीपॉइंटर या वीपीटीआर कहा जाता है, इस ऑब्जेक्ट के छिपे हुए सदस्य के रूप में जोड़ा जाता है। जैसे, कंपाइलर को प्रत्येक वर्ग के कंस्ट्रक्टर (ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग) में छिपे हुए कोड को भी उत्पन्न करना चाहिए ताकि एक नए ऑब्जेक्ट के वर्चुअल टेबल पॉइंटर को उसके क्लास के वर्चुअल मेथड टेबल के पते पर आवाक्षरित किया जा सके।

कई कंपाइलर वर्चुअल टेबल पॉइंटर को ऑब्जेक्ट के अंतिम सदस्य के रूप में रखते हैं; अन्य संकलक इसे पहले स्थान पर रखते हैं; सुवाह्य स्रोत कोड किसी भी तरह से काम करता है।[2]

उदाहरण के लिए, g++ ने पहले पॉइंटर को ऑब्जेक्ट के अंत में रखा था। [3]


उदाहरण

सी ++ सिंटैक्स में निम्नलिखित वर्ग घोषणाओं पर विचार करें:

class B1 {
public:
  virtual ~B1() {}
  void fnonvirtual() {}
  virtual void f1() {}
  int int_in_b1;
};

class B2 {
public:
  virtual ~B2() {}
  virtual void f2() {}
  int int_in_b2;
};

निम्नलिखित वर्ग प्राप्त करने के लिए प्रयोग किया जाता है:

class D : public B1, public B2 {
public:
  void d() {}
  void f2() override {}
  int int_in_d;
};

और सी ++ कोड का निम्न भाग:

B2 *b2 = new B2();
D  *d  = new D();

जीएनयू कंपाइलर संग्रह से जी ++ 3.4.6 वस्तु के लिए निम्नलिखित b232-बिट मेमोरी लेआउट उत्पन्न करता है: [nb 1] <पूर्व> बी 2:

B2 की वर्चुअल विधि तालिका:

 b2:
  +0: pointer to virtual method table of B2
  +4: value of int_in_b2

virtual method table of B2:
  +0: B2::f2()   

और ऑब्जेक्ट के लिए निम्न मेमोरी लेआउट d:

 d:
  +0: pointer to virtual method table of D (for B1)
  +4: value of int_in_b1
  +8: pointer to virtual method table of D (for B2)
 +12: value of int_in_b2
 +16: value of int_in_d

Total size: 20 Bytes.

virtual method table of D (for B1):
  +0: B1::f1()  // B1::f1() is not overridden

virtual method table of D (for B2):
  +0: D::f2()   // B2::f2() is overridden by D::f2()
                // The location of B2::f2 is not in the virtual method table for D

ध्यान दें कि वे कार्य virtualकीवर्ड नहीं ले रहे हैं उनकी घोषणा में (जैसे fnonvirtual() और d()) सामान्यतः वर्चुअल मेथड टेबल में दिखाई नहीं देते हैं। डिफ़ॉल्ट कंस्ट्रक्टर द्वारा उत्पन्न विशेष स्तिथियों के अपवाद हैं।

वर्चुअल फलन में वर्चुअल डिस्ट्रक्टर्स B1 और B2पर भी ध्यान दें। उन्हें सुनिश्चित करना आवश्यक है delete d न केवल स्मृति Dको मुक्त कर सकते हैं, बल्कि B1 और B2 के लिए भी मुक्त कर सकते हैं, अगर d एक सूचक या प्रकार का संदर्भ B1 या B2 है। उदाहरण को सरल रखने के लिए उन्हें मेमोरी लेआउट से बाहर रखा गया था। [nb 2]

ओवरराइडिंग विधि f2() कक्षा में D की वर्चुअल विधि तालिका को प्रतिलिपि करके कार्यान्वित किया जाता है और B2सूचक की जगह B2::f2() एक सूचक D::f2() के साथ है।

एकाधिक वंशानुक्रम और थंक्स

G++ कंपाइलर प्रत्येक बेस क्लास के लिए दो वर्चुअल मेथड टेबल का उपयोग करके क्लास D में क्लास B1और B2 के विविध इनहेरिटेंस को लागू करता है। (विविध इनहेरिटेंस को लागू करने के अन्य तरीके हैं, लेकिन यह सबसे सामान्य है।) यह पॉइंटर फिक्सअप की आवश्यकता की ओर ले जाता है, जिसे थंक (प्रोग्रामिंग) भी कहा जाता है, जब टाइप रूपांतरण होता है।

निम्नलिखित सी ++ कोड पर विचार करें:

D  *d  = new D();
B1 *b1 = d;
B2 *b2 = d;

जबकि d और b1 इस कोड के निष्पादन के बाद उसी स्मृति स्थान को इंगित करेगा, b2 स्थान की ओर संकेत करेगा d+8 (आठ बाइट्स की स्मृति स्थान से परे d)। इस प्रकार, b2 भीतर के क्षेत्र की ओर इशारा करता है d का एक उदाहरण B2 लगता है, यानी, एक उदाहरण के रूप में एक ही मेमोरी लेआउट B2 है।

आघोष

d->f1()को एक कॉल अपसंदर्भन द्वारा नियंत्रित किया जाता है d'एस D::B1 वीपॉइंटर, ऊपर f1देख रहा है। वर्चुअल मेथड टेबल में एंट्री, और फिर कोड को कॉल करने के लिए उस पॉइंटर को अपसंदर्भन करना है।

एकल वंशानुक्रम

एकल वंशानुक्रम (या केवल एकल वंशानुक्रम वाली भाषा में) की स्तिथि में, यदि वीपॉइंटर हमेशा पहला तत्व d होता है (जैसा कि यह कई कंपाइलर्स के साथ है), यह निम्न छद्म-C ++ को कम करता है:

(*((*d)[0]))(d)

जहाँ *d की वर्चुअल विधि तालिका को संदर्भित करता है, D और [0] वर्चुअल विधि तालिका में पहली विधि को संदर्भित करता है। मापदण्ड d यह (कंप्यूटर विज्ञान) बन जाता है |thisवस्तु के लिए सूचक है।

एकाधिक वंशानुक्रम

अधिक सामान्य स्तिथि में, कॉलिंग B1::f1() या D::f2() अधिक जटिल है:

(*(*(d[+0]/*pointer to virtual method table of D (for B1)*/)[0]))(d)   /* Call d->f1() */
(*(*(d[+8]/*pointer to virtual method table of D (for B2)*/)[0]))(d+8) /* Call d->f2() */

d->f1()पर कॉल एक मापदण्ड के रूप में B1 पॉइंटर को पास करती है। d->f2() पर कॉल एक मापदण्ड के रूप में B2 पॉइंटर को पास करती है। इस दूसरी कॉल के लिए सही पॉइंटर उत्पन्न करने के लिए फ़िक्सअप की आवश्यकता होती है। B2::f2 का स्थान D के लिए वर्चुअल विधि तालिका में नहीं है।

तुलनात्मक रूप से, d->fnonvirtual() पर कॉल करना बहुत आसान है:

(*B1::fnonvirtual)(d)


दक्षता

एक गैर-वर्चुअल कॉल की तुलना में एक वर्चुअल कॉल के लिए कम से कम एक अतिरिक्त अनुक्रमित डीरेफरेंस और कभी-कभी एक फिक्सअप जोड़ की आवश्यकता होती है, जो केवल संकलित-इन पॉइंटर के लिए एक विषयांतर है। इसलिए, वर्चुअल फलन को कॉल करना गैर-वर्चुअल फलन को कॉल करने की तुलना में स्वाभाविक रूप से धीमा है। 1996 में किए गए एक प्रयोग से संकेत मिलता है कि निष्पादन समय का लगभग 6-13% केवल सही कार्य को भेजने में व्यतीत होता है, हालांकि शिरोपरि 50% जितना अधिक हो सकता है। [4] आधुनिक कार्यों पर वर्चुअल कार्यों सीपीयू की लागत इतनी अधिक नहीं हो सकती है, बहुत बड़े कैश और बेहतर ब्रांच प्रेडिक्शन के कारण आर्किटेक्चर है।

इसके अतिरिक्त, ऐसे वातावरण में जहां समय-समय पर संकलन उपयोग में नहीं है, वर्चुअल फलन कॉल सामान्यतः इनलाइन विस्तार नहीं हो सकते हैं। कुछ स्तिथियों में संकलक के लिए यह संभव हो सकता है कि वह डिवर्चुअलाइज़ेशन के रूप में जानी जाने वाली प्रक्रिया को अंजाम दे, जिसमें उदाहरण के लिए, लुकअप और अप्रत्यक्ष कॉल को प्रत्येक इनलाइन बॉडी के सशर्त निष्पादन के साथ बदल दिया जाता है, लेकिन ऐसे अनुकूलन सामान्य नहीं हैं।

इस शिरोपरि से बचने के लिए, जब भी संकलन समय पर कॉल को हल किया जा सकता है, तो कंपाइलर सामान्यतः वर्चुअल मेथड टेबल का उपयोग करने से बचते हैं।

इस प्रकार, उपरोक्त f1 पर कॉल के लिए तालिका लुकअप की आवश्यकता नहीं हो सकती है क्योंकि कंपाइलर यह बताने में सक्षम हो सकता है कि d केवल इस बिंदु पर D को पकड़ सकता है, और D, f1 को ओवरराइड नहीं करता है। या कंपाइलर (या ऑप्टिमाइज़र) यह पता लगाने में सक्षम हो सकता है कि प्रोग्राम में कहीं भी B1 का कोई उपवर्ग नहीं है जो f1 को ओवरराइड करता हो। B1::f1 या B2::f2 पर कॉल के लिए संभवतः तालिका लुकअप की आवश्यकता नहीं होगी क्योंकि कार्यान्वयन स्पष्ट रूप से निर्दिष्ट है (हालांकि इसे अभी भी 'यह'-पॉइंटर फ़िक्सअप की आवश्यकता है)।

विकल्पों के साथ तुलना

डायनेमिक डिस्पैच प्राप्त करने के लिए वर्चुअल मेथड टेबल सामान्यतः एक अच्छा प्रदर्शन ट्रेड-ऑफ है, लेकिन उच्च प्रदर्शन के साथ बाइनरी ट्री डिस्पैच जैसे विकल्प हैं, लेकिन अलग-अलग लागतें हैं। [5] हालाँकि, वर्चुअल मेथड टेबल केवल विशेष मापदण्ड पर एकल प्रेषण की अनुमति देते हैं, एकाधिक प्रेषण (कॉमन लिस्प ऑब्जेक्ट सिस्टम, डायलन (प्रोग्रामिंग भाषा), या जूलिया (प्रोग्रामिंग भाषा)) के विपरीत, जहां सभी प्रकार के मापदण्ड हो सकते हैं भेजने में ध्यान में रखा जाना चाहिए।

वर्चुअल मेथड टेबल भी तभी काम करते हैं जब डिस्पैचिंग विधियों के ज्ञात सम्मुच्चय तक सीमित हो, इसलिए उन्हें डक टाइपिंग लैंग्वेज (जैसे स्मॉलटाक, पायथन (प्रोग्रामिंग लैंग्वेज) या जावास्क्रिप्ट) के विपरीत संकलन समय पर निर्मित एक साधारण सरणी में रखा जा सकता है।

ऐसी भाषाएँ जो इनमें से कोई एक या दोनों सुविधाएँ प्रदान करती हैं, प्रायः हैश तालिका में एक स्ट्रिंग या किसी अन्य समकक्ष विधि को देखकर प्रेषित होती हैं। इसे तेज़ बनाने के लिए कई तरह की तकनीकें हैं (उदाहरण के लिए, स्ट्रिंग इंटर्निंग/टोकनिंग विधि नाम, कैशिंग लुकअप, समय-समय पर संकलन)।

यह भी देखें

टिप्पणियाँ

  1. G++'s -fdump-class-hierarchy (starting with version 8: -fdump-lang-class) argument can be used to dump virtual method tables for manual inspection. For AIX VisualAge XlC compiler, use -qdump_class_hierarchy to dump class hierarchy and virtual function table layout.
  2. "C++ - why there are two virtual destructor in the virtual table and where is address of the non-virtual function (gcc4.6.3)".


संदर्भ

  1. Ellis & Stroustrup 1990, pp. 227–232
  2. Danny Kalev. "C++ Reference Guide: The Object Model II". 2003. Heading "Inheritance and Polymorphism" and "Multiple Inheritance".
  3. "सी ++ एबीआई बंद मुद्दे". Archived from the original on 25 July 2011. Retrieved 17 June 2011.{{cite web}}: CS1 maint: bot: original URL status unknown (link)
  4. Driesen, Karel and Hölzle, Urs, "The Direct Cost of Virtual Function Calls in C++", OOPSLA 1996
  5. Zendra, Olivier and Driesen, Karel, "Stress-testing Control Structures for Dynamic Dispatch in Java", pp. 105–118, Proceedings of the USENIX 2nd Java Virtual Machine Research and Technology Symposium, 2002 (JVM '02)