मैंने एक बेहतर पढ़ने के लिए एक वार्तालाप के रूप में अपना उत्तर दिया है:
हमें आभासी कार्यों की आवश्यकता क्यों है?
बहुरूपता के कारण।
बहुरूपता क्या है?
तथ्य यह है कि एक बेस पॉइंटर भी व्युत्पन्न प्रकार की वस्तुओं को इंगित कर सकता है।
बहुरूपता की यह परिभाषा आभासी कार्यों की आवश्यकता में कैसे नेतृत्व करती है?
खैर, जल्दी बंधन के माध्यम से ।
जल्दी बाध्यकारी क्या है?
C ++ में अर्ली बाइंडिंग (कंपाइल-टाइम बाइंडिंग) का मतलब है कि प्रोग्राम को निष्पादित करने से पहले एक फ़ंक्शन कॉल को ठीक किया गया है।
इसलिए...?
इसलिए यदि आप किसी फ़ंक्शन के पैरामीटर के रूप में आधार प्रकार का उपयोग करते हैं, तो कंपाइलर केवल बेस इंटरफेस को पहचान लेगा, और यदि आप उस फ़ंक्शन को व्युत्पन्न वर्गों से किसी भी तर्क के साथ कहते हैं, तो यह कटा हुआ हो जाता है, जो कि आप नहीं चाहते हैं।
यदि यह नहीं है कि हम क्या करना चाहते हैं, तो इसकी अनुमति क्यों है?
क्योंकि हमें बहुरूपता चाहिए!
फिर बहुरूपता का क्या फायदा?
आप किसी एकल फ़ंक्शन के पैरामीटर के रूप में एक बेस टाइप पॉइंटर का उपयोग कर सकते हैं, और फिर अपने प्रोग्राम के रन-टाइम में, आप किसी भी मुद्दे के बिना व्युत्पन्न प्रकार के इंटरफेस (जैसे उनके सदस्य कार्यों) में से प्रत्येक का उपयोग कर सकते हैं, उस एकल की डेरेफेरिंग का उपयोग करके आधार सूचक।
मुझे अभी भी नहीं पता है कि वर्चुअल फ़ंक्शंस कितने अच्छे हैं ...! और यह मेरा पहला सवाल था!
ठीक है, यह इसलिए है क्योंकि आपने अपना प्रश्न भी जल्द ही पूछ लिया है!
हमें आभासी कार्यों की आवश्यकता क्यों है?
मान लें कि आपने आधार सूचक के साथ एक फ़ंक्शन कहा, जिसमें उसके व्युत्पन्न वर्गों में से किसी एक वस्तु का पता था। जैसा कि हम इसके बारे में ऊपर बात कर चुके हैं, रन-टाइम में, यह पॉइंटर डीफ़र हो जाता है, अब तक बहुत अच्छा है, हालाँकि, हम एक विधि (== एक सदस्य फ़ंक्शन) "हमारे व्युत्पन्न वर्ग" से निष्पादित होने की उम्मीद करते हैं! हालांकि, एक ही विधि (एक ही हैडर है) पहले से ही आधार वर्ग में परिभाषित किया गया है, इसलिए आपके कार्यक्रम को अन्य विधि चुनने के लिए क्यों परेशान होना चाहिए? दूसरे शब्दों में, मेरा मतलब है कि आप इस परिदृश्य को कैसे बता सकते हैं, जिसे हम सामान्य रूप से पहले देखते थे।
संक्षिप्त उत्तर "आधार में एक आभासी सदस्य फ़ंक्शन" है, और थोड़ा लंबा जवाब यह है कि, "इस कदम पर, यदि कार्यक्रम आधार वर्ग में एक आभासी फ़ंक्शन देखता है, तो यह पता चलता है (जिसे पता है) कि आप उपयोग करने की कोशिश कर रहे हैं बहुरूपता "और इसलिए व्युत्पन्न वर्गों ( v- तालिका का उपयोग करके , देर से बाध्यकारी का एक रूप) का उपयोग करके उस दूसरी विधि को खोजने के लिए जाता है करके उसी हेडर के साथ , लेकिन अप्रत्याशित रूप से एक अलग कार्यान्वयन।
एक अलग कार्यान्वयन क्यों?
आप ठक-ठक! एक अच्छी किताब पढ़ो !
ठीक है, प्रतीक्षा प्रतीक्षा प्रतीक्षा करें, कोई व्यक्ति आधार बिंदु का उपयोग करने के लिए परेशान क्यों होगा, जब वह / वह केवल व्युत्पन्न प्रकार के संकेत का उपयोग कर सकता है? आप जज हैं, क्या यह सब इसके लायक है? इन दो स्निपेट्स को देखें:
// 1:
Parent* p1 = &boy;
p1 -> task();
Parent* p2 = &girl;
p2 -> task();
// 2:
Boy* p1 = &boy;
p1 -> task();
Girl* p2 = &girl;
p2 -> task();
ठीक है, हालांकि मुझे लगता है कि 1 अभी भी 2 से बेहतर है , आप 1 लिख सकते हैं को इस तरह हैं:
// 1:
Parent* p1 = &boy;
p1 -> task();
p1 = &girl;
p1 -> task();
और इसके अलावा, आपको पता होना चाहिए कि यह अभी तक आपके द्वारा बताई गई सभी चीजों का केवल एक आकस्मिक उपयोग है। इसके बजाय, उदाहरण के लिए मान लें कि आपके प्रोग्राम में एक ऐसा फंक्शन था जिसमें क्रमशः व्युत्पन्न वर्गों में से प्रत्येक से तरीकों का उपयोग किया गया था (getMonthBenefit ()):
double totalMonthBenefit = 0;
std::vector<CentralShop*> mainShop = { &shop1, &shop2, &shop3, &shop4, &shop5, &shop6};
for(CentralShop* x : mainShop){
totalMonthBenefit += x -> getMonthBenefit();
}
अब, बिना किसी सिरदर्द के इसे फिर से लिखने का प्रयास करें !
double totalMonthBenefit=0;
Shop1* branch1 = &shop1;
Shop2* branch2 = &shop2;
Shop3* branch3 = &shop3;
Shop4* branch4 = &shop4;
Shop5* branch5 = &shop5;
Shop6* branch6 = &shop6;
totalMonthBenefit += branch1 -> getMonthBenefit();
totalMonthBenefit += branch2 -> getMonthBenefit();
totalMonthBenefit += branch3 -> getMonthBenefit();
totalMonthBenefit += branch4 -> getMonthBenefit();
totalMonthBenefit += branch5 -> getMonthBenefit();
totalMonthBenefit += branch6 -> getMonthBenefit();
और वास्तव में, यह अभी तक एक आकस्मिक उदाहरण हो सकता है!