विषय पर बढ़ें

अंतिम अद्यतन:2026-10-12

C++ virtual वर्चुअल फ़ंक्शन

लेखक के बारे में:

व्यक्तिगत WeChat सार्वजनिक अकाउंट:

wechat

1.वर्चुअल फ़ंक्शन और रनटाइम पॉलीमॉर्फ़िज़्म

संगत कोड: emp.cpp

वर्चुअल फ़ंक्शन का कॉल पॉइंट या रेफ़रेंस द्वारा इंगित ऑब्जेक्ट के टाइप पर निर्भर करता है, पॉइंटर या रेफ़रेंस के अपने टाइप पर नहीं।

2.vptr और vtable

देखें vptr_vtable की बातें

3.वर्चुअल फ़ंक्शन में डिफ़ॉल्ट पैरामीटर

संगत कोड: default_arg.cpp

डिफ़ॉल्ट पैरामीटर static binding से जुड़ते हैं, वर्चुअल फ़ंक्शन dynamic binding से। डिफ़ॉल्ट पैरामीटर का उपयोग पॉइंटर या रेफ़रेंस के अपने टाइप को देखकर होता है, ऑब्जेक्ट के टाइप से नहीं।

4.हो सकता है या नहीं

(1) क्या static फ़ंक्शन को वर्चुअल फ़ंक्शन घोषित किया जा सकता है?

इसके मुख्य कारण दो हैं:

static फ़ंक्शन को वर्चुअल फ़ंक्शन घोषित नहीं किया जा सकता, और न ही इसे const और volatile कीवर्ड से qualify किया जा सकता है

static मेंबर फ़ंक्शन किसी क्लास ऑब्जेक्ट या क्लास इंस्टेंस का नहीं होता, इसलिए इस फ़ंक्शन पर virtual लगाने का कोई मतलब नहीं है

वर्चुअल फ़ंक्शन vptr और vtable पर काम करते हैं। vptr एक पॉइंटर है, क्लास के कंस्ट्रक्टर में बनता है, और इसे केवल this पॉइंटर से एक्सेस किया जा सकता है, static मेंबर फ़ंक्शन में this पॉइंटर नहीं होता, इसलिए vptr एक्सेस नहीं हो सकता।

कोड सीखें: static_error.cpp

(2)क्या कंस्ट्रक्टर वर्चुअल फ़ंक्शन हो सकता है?

कंस्ट्रक्टर को वर्चुअल फ़ंक्शन घोषित नहीं किया जा सकता। साथ ही inline|explicit के अलावा कंस्ट्रक्टर में कोई और कीवर्ड उपयोग करने की अनुमति नहीं है।

कंस्ट्रक्टर वर्चुअल फ़ंक्शन क्यों नहीं हो सकता?

भले ही वर्चुअल फ़ंक्शन टेबल vtable कंपाइल चरण में ही बन जाती है, पर वर्चुअल फ़ंक्शन टेबल की ओर पॉइंट करने वाला vptr रनटाइम में इंस्टेंस ऑब्जेक्ट बनते समय पैदा होता है। अगर क्लास में वर्चुअल फ़ंक्शन हैं, तो कंपाइलर कंस्ट्रक्टर में vptr बनाने का कोड जोड़ता है। समस्या यह है कि अगर कंस्ट्रक्टर वर्चुअल हो, तो उसे vtable एक्सेस करने के लिए vptr चाहिए, पर उस समय vptr अभी पैदा नहीं हुआ। इसलिए कंस्ट्रक्टर वर्चुअल फ़ंक्शन नहीं हो सकता।

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

कोड सीखें:

(3)क्या डिस्ट्रक्टर वर्चुअल फ़ंक्शन हो सकता है?

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

कोड सीखें:

(4)क्या वर्चुअल फ़ंक्शन private फ़ंक्शन हो सकता है?

  • बेस क्लास पॉइंटरderived क्लास ऑब्जेक्ट की ओर पॉइंट करे, तोderived क्लास ऑब्जेक्ट का फ़ंक्शन कॉल होगा;
  • int main() को Base क्लास का friend घोषित करना होगा, वरना कंपाइल नहीं होगा। कंपाइलर error देता है: ptr private फ़ंक्शन एक्सेस नहीं कर सकता। बेशक, बेस क्लास को public औरderived क्लास को private करने पर यह समस्या ख़त्म हो जाती है।

कोड सीखें:

(5)क्या वर्चुअल फ़ंक्शन inline हो सकता है?

आमतौर पर कंपाइलर क्लास मेंबर फ़ंक्शन पर inline करने की सोच रखता है। लेकिन बेस क्लास पॉइंटर या रेफ़रेंस से कॉल किया गया वर्चुअल फ़ंक्शन कभी inline नहीं हो सकता। बेशक, वास्तविक ऑब्जेक्ट द्वारा वर्चुअल फ़ंक्शन कॉल या static कॉल inline हो सकता है, और वर्चुअल डिस्ट्रक्टर का static कॉल भी ज़रूर inline expand होगा।

  • वर्चुअल फ़ंक्शन inline फ़ंक्शन हो सकता है, inline वर्चुअल फ़ंक्शन को qualify कर सकता है, लेकिन जब वर्चुअल फ़ंक्शन पॉलीमॉर्फ़िज़्म दिखाता है तब inline नहीं हो सकता।
  • inline प्रोग्रामर की ओर से कंपाइलर को inline करने का सुझाव है, जबकि वर्चुअल फ़ंक्शन का पॉलीमॉर्फ़िज़्म रनटाइम में होता है, कंपाइलर नहीं जानता कि रनटाइम में कौन-सा कोड कॉल होगा, इसलिए जब वर्चुअल फ़ंक्शन पॉलीमॉर्फ़िज़्म दिखाता है (रनटाइम) तब inline नहीं हो सकता।
  • inline virtual केवल तब inline हो सकता है जब कंपाइलर जानता हो कि कॉल किया गया ऑब्जेक्ट किस क्लास का है (जैसे Base::who()), यह केवल तब होता है जब कंपाइलर के पास वास्तविक ऑब्जेक्ट हो, ऑब्जेक्ट का पॉइंटर या रेफ़रेंस नहीं।

कोड सीखें:

5.RTTI और dynamic_cast

RTTI (Run-Time Type Identification) से रनटाइम टाइप जानकारी के ज़रिए प्रोग्राम बेस क्लास के पॉइंटर या रेफ़रेंस से जाँच सकता है कि इन पॉइंटरों या रेफ़रेंस द्वारा इंगित ऑब्जेक्ट का वास्तविक derived क्लास टाइप क्या है।

ऑब्जेक्ट-ओरिएंटेड प्रोग्राम डिज़ाइन में कभी-कभी हमें रनटाइम में जाँचने की ज़रूरत होती है कि कोई ऑब्जेक्ट किसी पॉलीमॉर्फ़िक टाइप की तरह उपयोग हो सकता है या नहीं। Java के instanceof और C# के as, is ऑपरेटरों की तरह, C++ dynamic_cast फ़ंक्शन देता है जो dynamic type conversion करता है। C-स्टाइल cast और C++ reinterpret_cast की तुलना में dynamic_cast टाइप सुरक्षा जाँच देता है, यह Capability Query पर आधारित conversion है, इसलिए पॉलीमॉर्फ़िक टाइप्स के बीच conversion के लिए dynamic_cast की सिफ़ारिश की जाती है।

कोड सीखें:

6.प्योर वर्चुअल फ़ंक्शन और एब्स्ट्रैक्ट क्लास

देखें प्योर वर्चुअल फ़ंक्शन और एब्स्ट्रैक्ट क्लास की बातें

संबंधित विषय

टिप्पणियाँ