वर्चुअल फंक्शन: Difference between revisions

From Vigyanwiki
No edit summary
No edit summary
Line 8: Line 8:
वर्चुअल फ़ंक्शन की अवधारणा निम्न समस्या हल करती है:
वर्चुअल फ़ंक्शन की अवधारणा निम्न समस्या हल करती है:


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


आभासी कार्यों को 'देर' से हल किया जाता है। यदि विचाराधीन फ़ंक्शन बेस क्लास में 'वर्चुअल' है, तो फ़ंक्शन के सबसे व्युत्पन्न वर्ग के कार्यान्वयन को पॉइंटर या संदर्भ के घोषित प्रकार की परवाह किए बिना संदर्भित वस्तु के वास्तविक प्रकार के अनुसार कहा जाता है। यदि यह 'आभासी' नहीं है, तो विधि 'प्रारंभिक' हल हो जाती है और सूचक या संदर्भ के घोषित प्रकार के अनुसार चुनी जाती है।
वर्चुअल फंक्शन्सों को 'देर' से हल किया जाता है। यदि विचाराधीन फ़ंक्शन बेस क्लास में 'वर्चुअल' है, तो फ़ंक्शन के सबसे व्युत्पन्न क्लासेज के कार्यान्वन को पॉइंटर या संदर्भ के घोषित प्रकार की परवाह किए बिना संदर्भित वस्तु के वास्तविक प्रकार के अनुएब्स्ट्रैक्ट कहा जाता है। यदि यह 'वर्चुअल' नहीं है, तो विधि 'प्रारंभिक' हल हो जाती है और सूचक या संदर्भ के घोषित प्रकार के अनुएब्स्ट्रैक्ट चुनी जाती है।


वर्चुअल फ़ंक्शंस प्रोग्राम को उन विधियों को कॉल करने की अनुमति देते हैं जो कोड संकलित होने के समय जरूरी नहीं हैं।{{Citation needed|date=October 2021}}
वर्चुअल फ़ंक्शंस प्रोग्राम को उन विधियों को कॉल करने की अनुमति देते हैं जो कोड संकलित होने के समय जरूरी नहीं हैं।{{Citation needed|date=October 2021}}
C++ में, आभासी विधियों को जोड़कर घोषित किया जाता है {{Cpp|virtual}} बेस क्लास में फ़ंक्शन की घोषणा के लिए कीवर्ड यह संशोधक व्युत्पन्न कक्षाओं में उस पद्धति के सभी कार्यान्वयनों द्वारा विरासत में मिला है, जिसका अर्थ है कि वे एक-दूसरे को ओवर-राइड करना जारी रख सकते हैं और लेट-बाउंड हो सकते हैं, और यहां तक ​​​​कि अगर बेस क्लास के स्वामित्व वाली विधियां वर्चुअल विधि को कॉल करती हैं, तो वे इसके बजाय व्युत्पन्न विधि को कॉल करेंगे। ओवरलोडिंग तब होती है जब एक वर्ग में दो या दो से अधिक विधियों का एक ही विधि नाम होता है लेकिन अलग-अलग पैरामीटर होते हैं। ओवरराइडिंग का अर्थ है एक ही विधि नाम और मापदंडों के साथ दो विधियाँ होना। ओवरलोडिंग को फंक्शन मैचिंग और ओवरराइडिंग को डायनामिक फंक्शन मैपिंग भी कहा जाता है।
C++ में, वर्चुअल विधियों को जोड़कर घोषित किया जाता है {{Cpp|virtual}} बेस क्लास में फ़ंक्शन की घोषणा के लिए कीवर्ड यह संशोधक व्युत्पन्न कक्षाओं में उस पद्धति के सभी कार्यान्वनों द्वारा वंशागति में मिला है, जिसका अर्थ है कि वे एक-दूसरे को ओवर-राइड करना जारी रख सकते हैं और लेट-बाउंड हो सकते हैं, और यहां तक ​​​​कि अगर बेस क्लास के स्वामित्व वाली विधियां वर्चुअल विधि को कॉल करती हैं, तो वे इसके बजाय व्युत्पन्न विधि को कॉल करेंगे। ओवरलोडिंग तब होती है जब एक क्लासेज में दो या दो से अधिक विधियों का एक ही विधि नाम होता है लेकिन अलग-अलग पैरामीटर होते हैं। ओवरराइडिंग का अर्थ है एक ही विधि नाम और मापदंडों के साथ दो विधियाँ होना। ओवरलोडिंग को फंक्शन मैचिंग और ओवरराइडिंग को डायनामिक फंक्शन मैपिंग भी कहा जाता है।


== उदाहरण ==
== उदाहरण ==


=== सी ++ ===
=== सी ++ ===
[[Image:ClassDiagram for VirtualFunction.png|400px|thumb|right|जानवरों का वर्ग आरेख]]उदाहरण के लिए, एक आधार वर्ग <code>Animal</code> वर्चुअल फ़ंक्शन हो सकता है <code>Eat</code>. उपवर्ग <code>Llama</code> लागू करेगा <code>Eat</code> उपवर्ग से अलग <code>Wolf</code>, लेकिन कोई आह्वान कर सकता है <code>Eat</code> Animal के रूप में संदर्भित किसी भी वर्ग के उदाहरण पर, और प्राप्त करें <code>Eat</code> विशिष्ट उपवर्ग का व्यवहार।
[[Image:ClassDiagram for VirtualFunction.png|400px|thumb|right|जानवरों का क्लासेज आरेख]]उदाहरण के लिए, एक आधार क्लासेज <code>Animal</code> वर्चुअल फ़ंक्शन हो सकता है <code>Eat</code>. उपक्लासेज <code>Llama</code> लागू करेगा <code>Eat</code> उपक्लासेज से अलग <code>Wolf</code>, लेकिन कोई आह्वान कर सकता है <code>Eat</code> Animal के रूप में संदर्भित किसी भी क्लासेज के उदाहरण पर, और प्राप्त करें <code>Eat</code> विशिष्ट उपक्लासेज का व्यवहार।


<syntaxhighlight lang="cpp">
<syntaxhighlight lang="cpp">
Line 42: Line 42:
यह एक प्रोग्रामर को क्लास के ऑब्जेक्ट्स की सूची को प्रोसेस करने की अनुमति देता है <code>Animal</code>प्रत्येक को बारी-बारी से खाने<code>(Eat</code>) के लिए कहना (कॉल करके)। यह जानने की आवश्यकता के बिना कि सूची में किस प्रकार का जानवर हो सकता है, प्रत्येक जानवर कैसे खाता है, या संभावित प्रकार के जानवरों का पूरा सेट क्या हो सकता है।
यह एक प्रोग्रामर को क्लास के ऑब्जेक्ट्स की सूची को प्रोसेस करने की अनुमति देता है <code>Animal</code>प्रत्येक को बारी-बारी से खाने<code>(Eat</code>) के लिए कहना (कॉल करके)। यह जानने की आवश्यकता के बिना कि सूची में किस प्रकार का जानवर हो सकता है, प्रत्येक जानवर कैसे खाता है, या संभावित प्रकार के जानवरों का पूरा सेट क्या हो सकता है।


C में, आभासी कार्यों के पीछे का तंत्र निम्नलिखित तरीके से प्रदान किया जा सकता है:
C में, वर्चुअल फंक्शन्सों के पीछे का तंत्र निम्नलिखित तरीके से प्रदान किया जा सकता है:
<syntaxhighlight lang="c">
<syntaxhighlight lang="c">
#include <stdio.h>
#include <stdio.h>
Line 109: Line 109:
[[Category:Templates Vigyan Ready|Virtual Function]]
[[Category:Templates Vigyan Ready|Virtual Function]]


== [[सार वर्ग]] और शुद्ध आभासी कार्य ==
== [[सार वर्ग|एब्स्ट्रैक्ट क्लासेज]] और शुद्ध वर्चुअल फंक्शन्स ==
'''एक शुद्ध वर्चुअल फ़ंक्शन''' या शुद्ध वर्चुअल विधि एक वर्चुअल फ़ंक्शन है जिसे व्युत्पन्न वर्ग द्वारा लागू किया जाना आवश्यक है यदि व्युत्पन्न वर्ग [[सार प्रकार]] नहीं है। शुद्ध आभासी विधियों वाली कक्षाओं को सार कहा जाता है और उन्हें सीधे तत्काल नहीं किया जा सकता है। एक सार वर्ग का एक [[उपवर्ग (कंप्यूटर विज्ञान)]] केवल सीधे ही तत्काल किया जा सकता है यदि सभी विरासत में मिली शुद्ध आभासी विधियों को उस वर्ग या मूल वर्ग द्वारा लागू किया गया हो। शुद्ध आभासी तरीकों में आमतौर पर एक घोषणा (प्रकार हस्ताक्षर # विधि हस्ताक्षर) होती है और कोई परिभाषा नहीं होती है ([[विधि कार्यान्वयन]])।
एक शुद्ध वर्चुअल फ़ंक्शन या शुद्ध वर्चुअल विधि एक वर्चुअल फ़ंक्शन है जिसे व्युत्पन्न क्लासेज द्वारा लागू किया जाना आवश्यक है यदि व्युत्पन्न क्लासेज [[सार प्रकार|एब्स्ट्रैक्ट प्रकार]] नहीं है तो शुद्ध वर्चुअल विधियों वाली कक्षाओं को एब्स्ट्रैक्ट कहा जाता है और उन्हें सीधे तत्काल नहीं किया जा सकता है। एक एब्स्ट्रैक्ट क्लासेज का एक [[उपवर्ग (कंप्यूटर विज्ञान)|उपक्लासेज (कंप्यूटर विज्ञान)]] केवल सीधे ही तत्काल किया जा सकता है यदि सभी वंशागति में मिली शुद्ध वर्चुअल विधियों को उस क्लासेज या मूल क्लासेज द्वारा लागू किया गया हो। शुद्ध वर्चुअल तरीकों में सामान्यतः एक घोषणा (प्रकार हस्ताक्षर, विधि हस्ताक्षर) होती है और कोई परिभाषा नहीं होती है ([[विधि कार्यान्वयन|विधि कार्यान्वन]])।


एक उदाहरण के रूप में, एक सार आधार वर्ग <code>MathSymbol</code> एक शुद्ध आभासी कार्य प्रदान कर सकता है <code>doOperation()</code>, और व्युत्पन्न वर्ग <code>Plus</code> और <code>Minus</code> अमल में लाना <code>doOperation()</code> ठोस कार्यान्वयन प्रदान करने के लिए। क्रियान्वयन <code>doOperation()</code> में कोई मतलब नहीं होगा <code>MathSymbol</code> वर्ग, के रूप में <code>MathSymbol</code> एक अमूर्त अवधारणा है जिसका व्यवहार केवल प्रत्येक दिए गए प्रकार (उपवर्ग) के लिए परिभाषित किया गया है <code>MathSymbol</code>. इसी तरह, एक दिया गया उपवर्ग <code>MathSymbol</code> के कार्यान्वयन के बिना पूरा नहीं होगा
एक उदाहरण के रूप में, एक एब्स्ट्रैक्ट आधार क्लासेज <code>MathSymbol</code> एक शुद्ध वर्चुअल फंक्शन्स प्रदान कर सकता है <code>doOperation()</code>, और व्युत्पन्न क्लासेज <code>Plus</code> और <code>Minus</code> अमल में लाना <code>doOperation()</code> ठोस कार्यान्वन प्रदान करने के लिए क्रियान्वयन <code>doOperation()</code> में कोई मतलब नहीं होगा, <code>MathSymbol</code> क्लासेज, के रूप में <code>MathSymbol</code> एक अमूर्त अवधारणा है जिसका व्यवहार केवल प्रत्येक दिए गए प्रकार (उपक्लासेज) के लिए परिभाषित किया गया है <code>MathSymbol</code>. इसी तरह, एक दिया गया उपक्लासेज <code>MathSymbol</code> के <code>doOperation()</code>कार्यान्वन के बिना पूरा नहीं होगा।
<code>doOperation()</code>.


हालाँकि शुद्ध आभासी विधियों का आमतौर पर उस वर्ग में कोई कार्यान्वयन नहीं होता है जो उन्हें घोषित करता है, कुछ भाषाओं में शुद्ध आभासी विधियों (जैसे C ++ और पायथन) को उनके घोषित वर्ग में कार्यान्वयन शामिल करने की अनुमति है, फ़ॉलबैक या डिफ़ॉल्ट व्यवहार प्रदान करता है जिसे एक व्युत्पन्न वर्ग प्रतिनिधि कर सकता है। , अगर उचित है।<ref>[https://en.cppreference.com/w/cpp/language/destructor#Pure_virtual_destructors Pure virtual destructors - cppreference.com]</ref><ref>[https://docs.python.org/3/library/abc.html "abc — Abstract Base Classes: @abc.abstractmethod"]</ref>
हालाँकि शुद्ध वर्चुअल विधियों का सामान्यतः उस क्लासेज में कोई कार्यान्वन नहीं होता है जो उन्हें घोषित करता है, कुछ भाषाओं में शुद्ध वर्चुअल विधियों (जैसे C ++ और पायथन) को उनके घोषित क्लासेज में कार्यान्वन सम्मिलित करने की अनुमति है, फ़ॉलबैक या डिफ़ॉल्ट व्यवहार प्रदान करता है जिसे एक व्युत्पन्न क्लासेज प्रतिनिधि कर सकता है। अगर उचित है<ref>[https://en.cppreference.com/w/cpp/language/destructor#Pure_virtual_destructors Pure virtual destructors - cppreference.com]</ref><ref>[https://docs.python.org/3/library/abc.html "abc — Abstract Base Classes: @abc.abstractmethod"]</ref> तो शुद्ध वर्चुअल फंक्शन्सों का भी उपयोग किया जा सकता है जहां [[इंटरफ़ेस (जावा)]] को परिभाषित करने के लिए विधि घोषणाओं का उपयोग किया जा रहा है - जैसा कि जावा में इंटरफ़ेस कीवर्ड स्पष्ट रूप से निर्दिष्ट करता है। ऐसे उपयोग में, व्युत्पन्न क्लासेज सभी कार्यान्वनों की आपूर्ति करेगा। इस तरह के एक [[डिज़ाइन पैटर्न]] में, इंटरफ़ेस के रूप में फंक्शन्स करने वाले एब्स्ट्रैक्ट क्लासेज में केवल शुद्ध वर्चुअल फंक्शन्स होंगे, लेकिन कोई डेटा सदस्य या साधारण तरीके नहीं होंगे। सी ++ में, इंटरफेस के रूप में ऐसे पूरी तरह से एब्स्ट्रैक्ट क्लासेजों का उपयोग करना काम करता है क्योंकि सी ++ एकाधिक वंशागति का समर्थन करता है। हालाँकि, क्योंकि कई OOP भाषाएँ [[एकाधिक वंशानुक्रम]] का समर्थन नहीं करती हैं, वे प्रायः एक अलग इंटरफ़ेस तंत्र प्रदान करते हैं। एक उदाहरण जावा (प्रोग्रामिंग भाषा) है।
शुद्ध आभासी कार्यों का भी उपयोग किया जा सकता है जहां [[इंटरफ़ेस (जावा)]] को परिभाषित करने के लिए विधि घोषणाओं का उपयोग किया जा रहा है - जैसा कि जावा में इंटरफ़ेस कीवर्ड स्पष्ट रूप से निर्दिष्ट करता है। ऐसे उपयोग में, व्युत्पन्न वर्ग सभी कार्यान्वयनों की आपूर्ति करेगा। इस तरह के एक [[डिज़ाइन पैटर्न]] में, इंटरफ़ेस के रूप में कार्य करने वाले सार वर्ग में केवल शुद्ध आभासी कार्य होंगे, लेकिन कोई डेटा सदस्य या साधारण तरीके नहीं होंगे। सी ++ में, इंटरफेस के रूप में ऐसे पूरी तरह से सार वर्गों का उपयोग करना काम करता है क्योंकि सी ++ एकाधिक विरासत का समर्थन करता है। हालाँकि, क्योंकि कई OOP भाषाएँ [[एकाधिक वंशानुक्रम]] का समर्थन नहीं करती हैं, वे अक्सर एक अलग इंटरफ़ेस तंत्र प्रदान करते हैं। एक उदाहरण जावा (प्रोग्रामिंग भाषा) है।


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


सी ++ में, बेस फ़ंक्शन कहा जाता है। विशेष रूप से, सबसे अधिक व्युत्पन्न कार्य जो वर्तमान निर्माता या विध्वंसक वर्ग से अधिक व्युत्पन्न नहीं है, कहलाता है।<ref name="cpp-std">{{cite web|url=http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/n4659.pdf|title=N4659: Working Draft, Standard for Programming Language C++}}</ref>{{rp|§15.7.3}}<ref name=chen>{{cite web |title=What is __purecall? |last=Chen|first=Raymond|author-link=Raymond Chen|date=April 28, 2004 |url=https://devblogs.microsoft.com/oldnewthing/20040428-00/?p=39613}}</ref><ref>{{cite web |title=Never Call Virtual Functions during Construction or Destruction |last=Meyers|first=Scott|author-link=Scott Meyers|date=June 6, 2005 |url=http://www.artima.com/cppsource/nevercall.html}}</ref> यदि वह कार्य एक शुद्ध आभासी कार्य है, तो [[अपरिभाषित व्यवहार]] होता है।<ref name="cpp-std"/>{{rp|§13.4.6}}<ref name=chen />यह सच है भले ही कक्षा में उस शुद्ध वर्चुअल फ़ंक्शन के लिए कार्यान्वयन हो, क्योंकि शुद्ध वर्चुअल फ़ंक्शन के लिए कॉल स्पष्ट रूप से योग्य होना चाहिए।<ref>{{cite web |title=C++ corner case: You can implement pure virtual functions in the base class |last=Chen|first=Raymond|author-link=Raymond Chen|date=October 11, 2013 |url=https://devblogs.microsoft.com/oldnewthing/20131011-00/?p=2953}}</ref> [[संकलन समय]] या [[लिंक समय]] पर शुद्ध आभासी कार्यों के लिए अप्रत्यक्ष कॉल का पता लगाने के लिए एक अनुरूप सी ++ कार्यान्वयन की आवश्यकता नहीं है (और आमतौर पर सक्षम नहीं)। रनटाइम (प्रोग्राम लाइफसाइकिल चरण) पर शुद्ध वर्चुअल फ़ंक्शन के लिए कॉल का सामना करते समय कुछ [[रनटाइम सिस्टम]] शुद्ध वर्चुअल फ़ंक्शन कॉल त्रुटि जारी करेंगे।
सी ++ में, बेस फ़ंक्शन कहा जाता है। विशेष रूप से, सबसे अधिक व्युत्पन्न फंक्शन्स जो वर्तमान निर्माता या विध्वंसक क्लासेज से अधिक व्युत्पन्न नहीं कहलाता है।<ref name="cpp-std">{{cite web|url=http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/n4659.pdf|title=N4659: Working Draft, Standard for Programming Language C++}}</ref>{{rp|§15.7.3}}<ref name=chen>{{cite web |title=What is __purecall? |last=Chen|first=Raymond|author-link=Raymond Chen|date=April 28, 2004 |url=https://devblogs.microsoft.com/oldnewthing/20040428-00/?p=39613}}</ref><ref>{{cite web |title=Never Call Virtual Functions during Construction or Destruction |last=Meyers|first=Scott|author-link=Scott Meyers|date=June 6, 2005 |url=http://www.artima.com/cppsource/nevercall.html}}</ref> यदि वह फंक्शन्स एक शुद्ध वर्चुअल फंक्शन्स है, तो [[अपरिभाषित व्यवहार]] होता है।<ref name="cpp-std"/>{{rp|§13.4.6}}<ref name=chen />यह सच है भले ही कक्षा में उस शुद्ध वर्चुअल फ़ंक्शन के लिए कार्यान्वन हो, क्योंकि शुद्ध वर्चुअल फ़ंक्शन के लिए कॉल स्पष्ट रूप से योग्य होना चाहिए।<ref>{{cite web |title=C++ corner case: You can implement pure virtual functions in the base class |last=Chen|first=Raymond|author-link=Raymond Chen|date=October 11, 2013 |url=https://devblogs.microsoft.com/oldnewthing/20131011-00/?p=2953}}</ref> [[संकलन समय]] या [[लिंक समय]] पर शुद्ध वर्चुअल फंक्शन्सों के लिए अप्रत्यक्ष कॉल का पता लगाने के लिए एक अनुरूप सी ++ कार्यान्वन की आवश्यकता नहीं है (और सामान्यतः सक्षम नहीं)। रनटाइम (प्रोग्राम लाइफसाइकिल चरण) पर शुद्ध वर्चुअल फ़ंक्शन के लिए कॉल का सामना करते समय कुछ [[रनटाइम सिस्टम]] शुद्ध वर्चुअल फ़ंक्शन कॉल त्रुटि जारी करेंगे।


जावा और सी # में, व्युत्पन्न कार्यान्वयन कहा जाता है, लेकिन कुछ क्षेत्रों को अभी तक व्युत्पन्न कन्स्ट्रक्टर द्वारा प्रारंभ नहीं किया गया है (हालांकि वे अपने डिफ़ॉल्ट शून्य मानों में प्रारंभ किए गए हैं)।<ref>{{cite web |title=Joy of Programming: Calling Virtual Functions from Constructors |last=Ganesh|first=S.G.|date=August 1, 2011 |url=https://www.opensourceforu.com/2011/08/joy-of-programming-calling-virtual-functions-from-constructors/}}</ref> कुछ डिज़ाइन पैटर्न (कंप्यूटर विज्ञान), जैसे [[सार फैक्टरी पैटर्न]], इस क्षमता का समर्थन करने वाली भाषाओं में सक्रिय रूप से इस उपयोग को बढ़ावा देते हैं।
जावा और सी # में, व्युत्पन्न कार्यान्वन कहा जाता है, लेकिन कुछ क्षेत्रों को अभी तक व्युत्पन्न कन्स्ट्रक्टर द्वारा प्रारंभ नहीं किया गया है (हालांकि वे अपने डिफ़ॉल्ट शून्य मानों में प्रारंभ किए गए हैं)।<ref>{{cite web |title=Joy of Programming: Calling Virtual Functions from Constructors |last=Ganesh|first=S.G.|date=August 1, 2011 |url=https://www.opensourceforu.com/2011/08/joy-of-programming-calling-virtual-functions-from-constructors/}}</ref> कुछ डिज़ाइन पैटर्न (कंप्यूटर विज्ञान), जैसे [[सार फैक्टरी पैटर्न|एब्स्ट्रैक्ट फैक्टरी पैटर्न]], इस क्षमता का समर्थन करने वाली भाषाओं में सक्रिय रूप से इस उपयोग को बढ़ावा देते हैं।


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


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


== यह भी देखें ==
== यह भी देखें ==
* [[सार विधि]]
* [[सार विधि|एब्स्ट्रैक्ट विधि]]
* [[वंशानुक्रम (कंप्यूटर विज्ञान)]]
* [[वंशानुक्रम (कंप्यूटर विज्ञान)]]
* सुपर क्लास (कंप्यूटर साइंस)
* सुपर क्लास (कंप्यूटर साइंस)
* [[आभासी विरासत]]
* [[आभासी विरासत|वर्चुअल वंशागति]]
*[[वर्चुअल क्लास]]
*[[वर्चुअल क्लास]]
* इंटरफ़ेस (ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग)
* इंटरफ़ेस (ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग)
* [[घटक वस्तु मॉडल]]
* [[घटक वस्तु मॉडल]]
* [[आभासी विधि तालिका]]
* [[आभासी विधि तालिका|वर्चुअल विधि तालिका]]


==संदर्भ==
==संदर्भ==

Revision as of 14:24, 18 February 2023

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

अधिकांश प्रोग्रामिंग लैंग्वेज, जैसे कि जावास्क्रिप्ट, पीएचपी और पायथन (प्रोग्रामिंग लैंग्वेज), डिफ़ॉल्ट रूप से सभी तरीकों को वर्चुअल मानते हैं[1][2] और इस व्यवहार को बदलने के लिए संशोधक प्रदान न करें। हालाँकि, कुछ भाषाएँ संशोधक प्रदान करती हैं ताकि विधियों को व्युत्पन्न कक्षाओं द्वारा ओवरराइड होने से रोका जा सके (जैसे कि जावा में अंतिम कीवर्ड (प्रोग्रामिंग भाषा)[3] और पीएचपी[4]).

उद्देश्य

वर्चुअल फ़ंक्शन की अवधारणा निम्न समस्या हल करती है:

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

वर्चुअल फंक्शन्सों को 'देर' से हल किया जाता है। यदि विचाराधीन फ़ंक्शन बेस क्लास में 'वर्चुअल' है, तो फ़ंक्शन के सबसे व्युत्पन्न क्लासेज के कार्यान्वन को पॉइंटर या संदर्भ के घोषित प्रकार की परवाह किए बिना संदर्भित वस्तु के वास्तविक प्रकार के अनुएब्स्ट्रैक्ट कहा जाता है। यदि यह 'वर्चुअल' नहीं है, तो विधि 'प्रारंभिक' हल हो जाती है और सूचक या संदर्भ के घोषित प्रकार के अनुएब्स्ट्रैक्ट चुनी जाती है।

वर्चुअल फ़ंक्शंस प्रोग्राम को उन विधियों को कॉल करने की अनुमति देते हैं जो कोड संकलित होने के समय जरूरी नहीं हैं।[citation needed] C++ में, वर्चुअल विधियों को जोड़कर घोषित किया जाता है virtual बेस क्लास में फ़ंक्शन की घोषणा के लिए कीवर्ड यह संशोधक व्युत्पन्न कक्षाओं में उस पद्धति के सभी कार्यान्वनों द्वारा वंशागति में मिला है, जिसका अर्थ है कि वे एक-दूसरे को ओवर-राइड करना जारी रख सकते हैं और लेट-बाउंड हो सकते हैं, और यहां तक ​​​​कि अगर बेस क्लास के स्वामित्व वाली विधियां वर्चुअल विधि को कॉल करती हैं, तो वे इसके बजाय व्युत्पन्न विधि को कॉल करेंगे। ओवरलोडिंग तब होती है जब एक क्लासेज में दो या दो से अधिक विधियों का एक ही विधि नाम होता है लेकिन अलग-अलग पैरामीटर होते हैं। ओवरराइडिंग का अर्थ है एक ही विधि नाम और मापदंडों के साथ दो विधियाँ होना। ओवरलोडिंग को फंक्शन मैचिंग और ओवरराइडिंग को डायनामिक फंक्शन मैपिंग भी कहा जाता है।

उदाहरण

सी ++

जानवरों का क्लासेज आरेख

उदाहरण के लिए, एक आधार क्लासेज Animal वर्चुअल फ़ंक्शन हो सकता है Eat. उपक्लासेज Llama लागू करेगा Eat उपक्लासेज से अलग Wolf, लेकिन कोई आह्वान कर सकता है Eat Animal के रूप में संदर्भित किसी भी क्लासेज के उदाहरण पर, और प्राप्त करें Eat विशिष्ट उपक्लासेज का व्यवहार।

class Animal {
 public:
  // Intentionally not virtual:
  void Move() {
    std::cout << "This animal moves in some way" << std::endl;
  }
  virtual void Eat() = 0;
};

// The class "Animal" may possess a definition for Eat if desired.
class Llama : public Animal {
 public:
  // The non virtual function Move is inherited but not overridden.
  void Eat() override {
    std::cout << "Llamas eat grass!" << std::endl;
  }
};

यह एक प्रोग्रामर को क्लास के ऑब्जेक्ट्स की सूची को प्रोसेस करने की अनुमति देता है Animalप्रत्येक को बारी-बारी से खाने(Eat) के लिए कहना (कॉल करके)। यह जानने की आवश्यकता के बिना कि सूची में किस प्रकार का जानवर हो सकता है, प्रत्येक जानवर कैसे खाता है, या संभावित प्रकार के जानवरों का पूरा सेट क्या हो सकता है।

C में, वर्चुअल फंक्शन्सों के पीछे का तंत्र निम्नलिखित तरीके से प्रदान किया जा सकता है:

#include <stdio.h>

/* an object points to its class... */
struct Animal {
    const struct AnimalClass * class;
};

/* which contains the virtual function Animal.Eat */
struct AnimalClass {
    void (*Eat)(struct Animal *); // 'virtual' function 
};

/* Since Animal.Move is not a virtual function
   it is not in the structure above. */
void Move(struct Animal * self)
{
    printf("<Animal at %p> moved in some way\n", (void *) self);
}

/* unlike Move, which executes Animal.Move directly,
   Eat cannot know which function (if any) to call at compile time.
   Animal.Eat can only be resolved at run time when Eat is called. */
void Eat(struct Animal * self)
{
    const struct AnimalClass * class = *(const void **) self;
    if (class->Eat) 
        class->Eat(self); // execute Animal.Eat
    else
        fprintf(stderr, "Eat not implemented\n");
}

/* implementation of Llama.Eat this is the target function 
   to be called by 'void Eat(struct Animal *).' */
static void _Llama_eat(struct Animal * self)
{
    printf("<Llama at %p> Llama's eat grass!\n", (void *) self);    
}

/* initialize class */
const struct AnimalClass Animal = {(void *) 0}; // base class does not implement Animal.Eat
const struct AnimalClass Llama = {_Llama_eat};  // but the derived class does

int main(void)
{
   /* init objects as instance of its class */
   struct Animal animal = {& Animal};
   struct Animal llama = {& Llama};
   Move(& animal); // Animal.Move
   Move(& llama);  // Llama.Move
   Eat(& animal);  // cannot resolve Animal.Eat so print "Not Implemented" to stderr
   Eat(& llama);   // resolves Llama.Eat and executes
}

एब्स्ट्रैक्ट क्लासेज और शुद्ध वर्चुअल फंक्शन्स

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

एक उदाहरण के रूप में, एक एब्स्ट्रैक्ट आधार क्लासेज MathSymbol एक शुद्ध वर्चुअल फंक्शन्स प्रदान कर सकता है doOperation(), और व्युत्पन्न क्लासेज Plus और Minus अमल में लाना doOperation() ठोस कार्यान्वन प्रदान करने के लिए क्रियान्वयन doOperation() में कोई मतलब नहीं होगा, MathSymbol क्लासेज, के रूप में MathSymbol एक अमूर्त अवधारणा है जिसका व्यवहार केवल प्रत्येक दिए गए प्रकार (उपक्लासेज) के लिए परिभाषित किया गया है MathSymbol. इसी तरह, एक दिया गया उपक्लासेज MathSymbol के doOperation()कार्यान्वन के बिना पूरा नहीं होगा।

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

कंस्ट्रक्शन और डिस्ट्रक्शन के दौरान व्यवहार

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

सी ++ में, बेस फ़ंक्शन कहा जाता है। विशेष रूप से, सबसे अधिक व्युत्पन्न फंक्शन्स जो वर्तमान निर्माता या विध्वंसक क्लासेज से अधिक व्युत्पन्न नहीं कहलाता है।[7]: §15.7.3 [8][9] यदि वह फंक्शन्स एक शुद्ध वर्चुअल फंक्शन्स है, तो अपरिभाषित व्यवहार होता है।[7]: §13.4.6 [8]यह सच है भले ही कक्षा में उस शुद्ध वर्चुअल फ़ंक्शन के लिए कार्यान्वन हो, क्योंकि शुद्ध वर्चुअल फ़ंक्शन के लिए कॉल स्पष्ट रूप से योग्य होना चाहिए।[10] संकलन समय या लिंक समय पर शुद्ध वर्चुअल फंक्शन्सों के लिए अप्रत्यक्ष कॉल का पता लगाने के लिए एक अनुरूप सी ++ कार्यान्वन की आवश्यकता नहीं है (और सामान्यतः सक्षम नहीं)। रनटाइम (प्रोग्राम लाइफसाइकिल चरण) पर शुद्ध वर्चुअल फ़ंक्शन के लिए कॉल का सामना करते समय कुछ रनटाइम सिस्टम शुद्ध वर्चुअल फ़ंक्शन कॉल त्रुटि जारी करेंगे।

जावा और सी # में, व्युत्पन्न कार्यान्वन कहा जाता है, लेकिन कुछ क्षेत्रों को अभी तक व्युत्पन्न कन्स्ट्रक्टर द्वारा प्रारंभ नहीं किया गया है (हालांकि वे अपने डिफ़ॉल्ट शून्य मानों में प्रारंभ किए गए हैं)।[11] कुछ डिज़ाइन पैटर्न (कंप्यूटर विज्ञान), जैसे एब्स्ट्रैक्ट फैक्टरी पैटर्न, इस क्षमता का समर्थन करने वाली भाषाओं में सक्रिय रूप से इस उपयोग को बढ़ावा देते हैं।

वर्चुअल डिस्ट्रक्शन

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

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

यह भी देखें

संदर्भ

  1. "Polymorphism (The Java™ Tutorials > Learning the Java Language > Interfaces and Inheritance)". docs.oracle.com. Retrieved 2020-07-11.
  2. "9. Classes — Python 3.9.2 documentation". docs.python.org. Retrieved 2021-02-23.
  3. "Writing Final Classes and Methods (The Java™ Tutorials > Learning the Java Language > Interfaces and Inheritance)". docs.oracle.com. Retrieved 2020-07-11.
  4. "PHP: Final Keyword - Manual". www.php.net. Retrieved 2020-07-11.
  5. Pure virtual destructors - cppreference.com
  6. "abc — Abstract Base Classes: @abc.abstractmethod"
  7. 7.0 7.1 "N4659: Working Draft, Standard for Programming Language C++" (PDF).
  8. 8.0 8.1 Chen, Raymond (April 28, 2004). "What is __purecall?".
  9. Meyers, Scott (June 6, 2005). "Never Call Virtual Functions during Construction or Destruction".
  10. Chen, Raymond (October 11, 2013). "C++ corner case: You can implement pure virtual functions in the base class".
  11. Ganesh, S.G. (August 1, 2011). "Joy of Programming: Calling Virtual Functions from Constructors".