C++ उदाहरण के साथ बहुरूपता
बहुरूपता क्या है? C++?
In C++, बहुरूपता एक सदस्य फ़ंक्शन को उस ऑब्जेक्ट के आधार पर अलग-अलग व्यवहार करने का कारण बनती है जो इसे कॉल/आह्वान करता है। बहुरूपता एक ग्रीक शब्द है जिसका अर्थ है कई रूप होना। यह तब होता है जब आपके पास विरासत के माध्यम से संबंधित कक्षाओं का पदानुक्रम होता है।
उदाहरण के लिए, मान लीजिए हमारे पास makeSound() फ़ंक्शन है। जब बिल्ली इस फ़ंक्शन को कॉल करती है, तो यह म्याऊँ की आवाज़ पैदा करेगी। जब गाय इसी फ़ंक्शन को कॉल करती है, तो यह म्याऊँ की आवाज़ पैदा करेगी।
हालाँकि हमारे पास एक फ़ंक्शन है, लेकिन यह अलग-अलग परिस्थितियों में अलग-अलग तरीके से व्यवहार करता है। फ़ंक्शन के कई रूप हैं; इसलिए, हमने बहुरूपता हासिल कर ली है।
बहुरूपता के प्रकार
C++ दो प्रकार के बहुरूपता का समर्थन करता है:
- संकलन-समय बहुरूपता, और
- रनटाइम बहुरूपता.
संकलन समय बहुरूपता
आप तर्कों की संख्या और प्रकार का मिलान करके ओवरलोडेड फ़ंक्शन को आमंत्रित करते हैं। जानकारी संकलन-समय के दौरान मौजूद रहती है। इसका मतलब है कि C++ कम्पाइलर संकलन समय पर सही फ़ंक्शन का चयन करेगा।
संकलन-समय बहुरूपता फ़ंक्शन ओवरलोडिंग और ऑपरेटर ओवरलोडिंग के माध्यम से प्राप्त की जाती है।
फंक्शन ओवरलोडिंग
फ़ंक्शन ओवरलोडिंग तब होती है जब हमारे पास समान नाम वाले कई फ़ंक्शन होते हैं लेकिन अलग-अलग तर्क होते हैं। तर्क संख्या या प्रकार के संदर्भ में भिन्न हो सकते हैं।
उदाहरण 1
#include <iostream> using namespace std; void test(int i) { cout << " The int is " << i << endl; } void test(double f) { cout << " The float is " << f << endl; } void test(char const *ch) { cout << " The char* is " << ch << endl; } int main() { test(5); test(5.5); test("five"); return 0; }
आउटपुट:
कोड का स्क्रीनशॉट यहां दिया गया है:
कोड स्पष्टीकरण:
- हमारे कोड में iostream हेडर फ़ाइल शामिल करें। हम इसके फ़ंक्शन का उपयोग करने में सक्षम होंगे।
- हमारे कोड में std नामस्थान शामिल करें। हम इसे कॉल किए बिना इसके क्लास का उपयोग कर सकेंगे।
- test नामक एक फ़ंक्शन बनाएँ जो एक पूर्णांक पैरामीटर i लेता है। { फ़ंक्शन test के मुख्य भाग की शुरुआत को चिह्नित करता है।
- यदि उपरोक्त फ़ंक्शन परीक्षण को लागू/बुलाया जाता है तो निष्पादित किया जाने वाला कथन।
- उपरोक्त फ़ंक्शन परीक्षण के मुख्य भाग का अंत.
- टेस्ट नामक एक फ़ंक्शन बनाएँ जो फ़्लोट पैरामीटर f लेता है। { फ़ंक्शन टेस्ट के मुख्य भाग की शुरुआत को चिह्नित करता है।
- यदि उपरोक्त फ़ंक्शन परीक्षण को लागू/बुलाया जाता है तो निष्पादित किया जाने वाला कथन।
- उपरोक्त फ़ंक्शन परीक्षण के मुख्य भाग का अंत.
- टेस्ट नामक एक फ़ंक्शन बनाएँ जो एक वर्ण पैरामीटर ch लेता है। { फ़ंक्शन टेस्ट के मुख्य भाग की शुरुआत को चिह्नित करता है।
- यदि उपरोक्त फ़ंक्शन परीक्षण को लागू/बुलाया जाता है तो निष्पादित किया जाने वाला कथन।
- उपरोक्त फ़ंक्शन परीक्षण के मुख्य भाग का अंत.
- main() फ़ंक्शन को कॉल करें। { फ़ंक्शन के मुख्य भाग की शुरुआत को चिह्नित करता है।
- फ़ंक्शन टेस्ट को कॉल करें और तर्क के मान के रूप में 5 पास करें। यह टेस्ट फ़ंक्शन को आमंत्रित करता है जो एक पूर्णांक तर्क स्वीकार करता है, यानी पहला टेस्ट फ़ंक्शन।
- फ़ंक्शन टेस्ट को कॉल करें और तर्क के मान के रूप में 5.5 पास करें। यह उस टेस्ट फ़ंक्शन को आमंत्रित करेगा जो फ़्लोट तर्क को स्वीकार करता है, यानी दूसरा टेस्ट फ़ंक्शन।
- फ़ंक्शन टेस्ट को कॉल करें और तर्क के मान के रूप में पाँच पास करें। यह टेस्ट फ़ंक्शन को आमंत्रित करेगा जो एक वर्ण तर्क स्वीकार करता है, यानी तीसरा टेस्ट फ़ंक्शन।
- यदि प्रोग्राम सफलतापूर्वक चलता है तो उसे एक मान अवश्य लौटाना चाहिए।
- main() फ़ंक्शन के मुख्य भाग का अंत.
हमारे पास एक ही नाम वाले तीन फ़ंक्शन हैं लेकिन अलग-अलग प्रकार के तर्क हैं। हमने बहुरूपता हासिल कर ली है।
Operaटोर ओवरलोडिंग
In Operaटोर ओवरलोडिंग, हम एक के लिए एक नया अर्थ परिभाषित करते हैं C++ ऑपरेटर। यह ऑपरेटर के काम करने के तरीके को भी बदलता है। उदाहरण के लिए, हम दो स्ट्रिंग को जोड़ने के लिए + ऑपरेटर को परिभाषित कर सकते हैं। हम इसे संख्यात्मक मानों को जोड़ने के लिए एडिशन ऑपरेटर के रूप में जानते हैं। हमारी परिभाषा के बाद, जब इसे पूर्णांकों के बीच रखा जाता है, तो यह उन्हें जोड़ देगा। जब इसे स्ट्रिंग के बीच रखा जाता है, तो यह उन्हें जोड़ देगा।
उदाहरण 2
#include<iostream> using namespace std; class ComplexNum { private: int real, over; public: ComplexNum(int rl = 0, int ov = 0) { real = rl; over = ov; } ComplexNum operator + (ComplexNum const &obj) { ComplexNum result; result.real = real + obj.real; result.over = over + obj.over; return result; } void print() { cout << real << " + i" << over << endl; } }; int main() { ComplexNum c1(10, 2), c2(3, 7); ComplexNum c3 = c1+c2; c3.print(); }
आउटपुट:
कोड का स्क्रीनशॉट यहां दिया गया है:
कोड स्पष्टीकरण:
- इसके कार्यों का उपयोग करने के लिए iostream हेडर फ़ाइल को हमारे प्रोग्राम में शामिल करें।
- अपने प्रोग्राम में std नामस्थान को शामिल करें ताकि इसे कॉल किए बिना इसके क्लासों का उपयोग किया जा सके।
- ComplexNum नामक एक क्लास बनाएँ। { क्लास बॉडी की शुरुआत को चिह्नित करता है।
- चरों को निजी के रूप में चिह्नित करने के लिए निजी पहुँच संशोधक का उपयोग करें, जिसका अर्थ है कि उन तक केवल वर्ग के भीतर से ही पहुँचा जा सकता है।
- दो पूर्णांक चर, वास्तविक और ओवर को परिभाषित करें।
- कन्स्ट्रक्टर को सार्वजनिक के रूप में चिह्नित करने के लिए सार्वजनिक एक्सेस संशोधक का उपयोग करें, जिसका अर्थ है कि यह बाहर से भी सुलभ होगा। कक्षा.
- क्लास कन्स्ट्रक्टर बनाएं और वेरिएबल्स को आरंभीकृत करें।
- चर real का मान आरंभ करें.
- चर का मान आरंभ करें.
- कन्स्ट्रक्टर बॉडी का अंत.
- हमें + ऑपरेटर के अर्थ को ओवरराइड करने की आवश्यकता है।
- ComplexNum प्रकार का डेटा प्रकार परिणाम बनाएँ.
- सम्मिश्र संख्याओं के साथ + ऑपरेटर का उपयोग करें। यह रेखा एक संख्या के वास्तविक भाग को दूसरी संख्या के वास्तविक भाग में जोड़ देगी।
- सम्मिश्र संख्याओं के साथ + ऑपरेटर का उपयोग करें। यह रेखा एक संख्या के काल्पनिक भाग को दूसरी संख्या के काल्पनिक भाग से जोड़ देगी।
- प्रोग्राम सफल निष्पादन पर चर परिणाम का मान लौटाएगा।
- + ऑपरेटर के नए अर्थ अर्थात ओवरलोडिंग की परिभाषा का अंत।
- print() विधि को कॉल करें.
- कंसोल पर जोड़ने के बाद नई जटिल संख्या प्रिंट करें।
- print() फ़ंक्शन के मुख्य भाग का अंत.
- ComplexNum वर्ग के मुख्य भाग का अंत.
- main() फ़ंक्शन को कॉल करें.
- जोड़ने के लिए वास्तविक और जटिल दोनों भागों के मान पास करें। c1 का पहला भाग c2 के पहले भाग में जोड़ा जाएगा, यानी 10+3। c1 का दूसरा भाग c के दूसरे भाग में जोड़ा जाएगा, यानी 2+7।
- ओवरलोडेड + ऑपरेटर का उपयोग करके एक ऑपरेशन निष्पादित करें और परिणाम को वेरिएबल c3 में संग्रहीत करें।
- कंसोल पर वेरिएबल c3 का मान प्रिंट करें।
- main() फ़ंक्शन के मुख्य भाग का अंत.
रनटाइम पॉलीमॉर्फिज़्म
ऐसा तब होता है जब किसी ऑब्जेक्ट की विधि को संकलन समय के बजाय रनटाइम के दौरान बुलाया/बुलाया जाता है। रनटाइम बहुरूपता फ़ंक्शन ओवरराइडिंग के माध्यम से प्राप्त की जाती है। कॉल/बुलाया जाने वाला फ़ंक्शन रनटाइम के दौरान स्थापित किया जाता है।
फंक्शन ओवरराइडिंग
फ़ंक्शन ओवरराइडिंग तब होती है जब बेस क्लास के फ़ंक्शन को व्युत्पन्न क्लास में एक नई परिभाषा दी जाती है। उस समय, हम कह सकते हैं कि बेस फ़ंक्शन को ओवरराइड कर दिया गया है।
उदाहरण के लिए:
#include <iostream> using namespace std; class Mammal { public: void eat() { cout << "Mammals eat..."; } }; class Cow: public Mammal { public: void eat() { cout << "Cows eat grass..."; } }; int main(void) { Cow c = Cow(); c.eat(); return 0; }
आउटपुट:
कोड का स्क्रीनशॉट यहां दिया गया है:
कोड स्पष्टीकरण:
- इसके कार्यों का उपयोग करने के लिए iostream हेडर फ़ाइल को हमारे प्रोग्राम में आयात करें।
- अपने प्रोग्राम में std नामस्थान को शामिल करें ताकि इसे कॉल किए बिना इसके क्लासों का उपयोग किया जा सके।
- Mammal नामक एक क्लास बनाएँ। { क्लास बॉडी की शुरुआत को चिह्नित करता है।
- हम जो फ़ंक्शन बनाने जा रहे हैं उसे सार्वजनिक रूप से सुलभ बनाने के लिए पब्लिक एक्सेस मॉडिफ़ायर का उपयोग करें। यह इस क्लास के बाहर से भी सुलभ होगा।
- eat नामक एक सार्वजनिक फ़ंक्शन बनाएँ। { फ़ंक्शन बॉडी की शुरुआत को चिह्नित करता है।
- जब फ़ंक्शन eat() को लागू किया जाता है तो cout फ़ंक्शन में जोड़ा गया कथन प्रिंट करें।
- फ़ंक्शन eat() के मुख्य भाग का अंत.
- स्तनपायी वर्ग के शरीर का अंतिम भाग।
- गाय नामक एक क्लास बनाएँ जो Mammal क्लास को इनहेरिट करती है। Cow व्युत्पन्न क्लास है, जबकि Mammal बेस क्लास है। { इस क्लास की शुरुआत को दर्शाता है।
- हम जिस फ़ंक्शन को बनाने जा रहे हैं उसे सार्वजनिक रूप से सुलभ के रूप में चिह्नित करने के लिए पब्लिक एक्सेस मॉडिफ़ायर का उपयोग करें। यह इस क्लास के बाहर से भी सुलभ होगा।
- बेस क्लास में परिभाषित फ़ंक्शन eat() को ओवरराइड करें। { फ़ंक्शन बॉडी की शुरुआत को चिह्नित करता है।
- जब यह फ़ंक्शन लागू किया जाता है तो कंसोल पर प्रिंट करने के लिए कथन.
- फ़ंक्शन eat() के मुख्य भाग का अंत.
- वर्ग गाय के शरीर का अंत.
- main() फ़ंक्शन को कॉल करें। { इस फ़ंक्शन के मुख्य भाग की शुरुआत को चिह्नित करता है।
- Cow क्लास का एक उदाहरण बनाएं और उसे c नाम दें।
- Cow क्लास में परिभाषित eat() फ़ंक्शन को कॉल करें।
- प्रोग्राम को सफलतापूर्वक पूरा होने पर एक मान लौटाना होगा।
- main() फ़ंक्शन का अंत.
C++ आभासी कार्य
वर्चुअल फ़ंक्शन रन-टाइम बहुरूपता को लागू करने का एक और तरीका है C++यह एक विशेष फ़ंक्शन है जिसे बेस क्लास में परिभाषित किया गया है और व्युत्पन्न क्लास में पुनः परिभाषित किया गया है। वर्चुअल फ़ंक्शन घोषित करने के लिए, आपको वर्चुअल कीवर्ड का उपयोग करना चाहिए। कीवर्ड को बेस क्लास में फ़ंक्शन की घोषणा से पहले होना चाहिए।
यदि कोई वर्चुअल फ़ंक्शन क्लास इनहेरिट की गई है, तो वर्चुअल क्लास अपनी ज़रूरतों के हिसाब से वर्चुअल फ़ंक्शन को फिर से परिभाषित करता है। उदाहरण के लिए:
#include <iostream> using namespace std; class ClassA { public: virtual void show() { cout << "The show() function in base class invoked..." << endl; } }; class ClassB :public ClassA { public: void show() { cout << "The show() function in derived class invoked..."; } }; int main() { ClassA* a; ClassB b; a = &b; a->show(); }
आउटपुट:
कोड का स्क्रीनशॉट यहां दिया गया है:
कोड स्पष्टीकरण:
- इसके फ़ंक्शन का उपयोग करने के लिए कोड में iostream हेडर फ़ाइल शामिल करें।
- अपने कोड में std नामस्थान को शामिल करें ताकि उसे कॉल किए बिना उसकी क्लासों का उपयोग किया जा सके।
- ClassA नामक एक क्लास बनाएं.
- किसी वर्ग सदस्य को सार्वजनिक रूप से सुलभ के रूप में चिह्नित करने के लिए सार्वजनिक पहुँच संशोधक का उपयोग करें।
- show() नाम से एक वर्चुअल फ़ंक्शन बनाएँ। यह एक सार्वजनिक फ़ंक्शन होगा।
- शो() को लागू करने पर प्रिंट करने के लिए पाठ। endl एक है C++ कीवर्ड, जिसका मतलब है अंतिम पंक्ति। यह माउस कर्सर को अगली पंक्ति पर ले जाता है।
- वर्चुअल फ़ंक्शन show() के मुख्य भाग का अंत.
- क्लास ClassA के मुख्य भाग का अंत.
- ClassB नामक एक नया वर्ग बनाना जो ClassA वर्ग को विरासत में लेता है। ClassA आधार वर्ग बन जाता है जबकि ClassB व्युत्पन्न वर्ग बन जाता है।
- किसी वर्ग सदस्य को सार्वजनिक रूप से सुलभ के रूप में चिह्नित करने के लिए सार्वजनिक पहुँच संशोधक का उपयोग करें।
- आधार वर्ग में व्युत्पन्न वर्चुअल फ़ंक्शन show() को पुनः परिभाषित करें।
- व्युत्पन्न वर्ग में परिभाषित show() फ़ंक्शन को लागू करने पर कंसोल पर मुद्रित होने वाला पाठ।
- show() फ़ंक्शन के मुख्य भाग का अंत.
- व्युत्पन्न वर्ग, ClassB के मुख्य भाग का अंत.
- main() फ़ंक्शन को कॉल करें। प्रोग्राम लॉजिक को इसके बॉडी में जोड़ा जाना चाहिए।
- a नाम से एक पॉइंटर वैरिएबल बनाएँ। यह ClassA नाम की क्लास की ओर इशारा करता है।
- ClassB नामक क्लास का एक इंस्टेंस बनाएँ। इंस्टेंस को b नाम दिया गया है।
- पता b में संग्रहीत मानों को चर a में निर्दिष्ट करें।
- व्युत्पन्न वर्ग में परिभाषित show() फ़ंक्शन को लागू करें। लेट बाइंडिंग को लागू किया गया है।
- main() फ़ंक्शन के मुख्य भाग का अंत.
संकलन-समय बहुरूपता बनाम रन-समय बहुरूपता
इन दोनों के बीच प्रमुख अंतर इस प्रकार हैं:
संकलन-समय बहुरूपता | रन-टाइम बहुरूपता |
---|---|
इसे प्रारंभिक बंधन या स्थैतिक बहुरूपता भी कहा जाता है | इसे लेट/डायनेमिक बाइंडिंग या डायनेमिक पॉलीमॉर्फिज्म भी कहा जाता है |
विधि को संकलन समय के दौरान बुलाया/आह्वान किया जाता है | विधि को रन टाइम के दौरान बुलाया/आह्वान किया जाता है |
फ़ंक्शन ओवरलोडिंग और ऑपरेटर ओवरलोडिंग के माध्यम से कार्यान्वित | विधि ओवरराइडिंग और वर्चुअल फ़ंक्शन के माध्यम से कार्यान्वित |
उदाहरण, विधि ओवरलोडिंग। कई विधियों के नाम समान हो सकते हैं लेकिन तर्कों की संख्या या प्रकार भिन्न हो सकते हैं | उदाहरण, विधि ओवरराइडिंग। कई विधियों का नाम और प्रोटोटाइप एक जैसा हो सकता है। |
तीव्र निष्पादन क्योंकि विधियों की खोज संकलन समय के दौरान की जाती है | धीमी गति से निष्पादन क्योंकि विधि खोज रनटाइम के दौरान किया जाता है। |
Less समस्या-समाधान के लिए लचीलापन प्रदान किया जाता है क्योंकि संकलन समय के दौरान सब कुछ ज्ञात होता है। | जटिल समस्याओं को सुलझाने के लिए काफी लचीलापन उपलब्ध होता है क्योंकि विधियां रनटाइम के दौरान ही खोजी जाती हैं। |
सारांश
- बहुरूपता का अर्थ है अनेक रूप होना।
- यह तब होता है जब वंशानुक्रम के माध्यम से संबंधित वर्गों का पदानुक्रम होता है।
- बहुरूपता के साथ, एक फ़ंक्शन उस ऑब्जेक्ट के आधार पर अलग-अलग व्यवहार कर सकता है जो उसे आमंत्रित/कॉल करता है।
- संकलन-समय बहुरूपता में, आह्वान किया जाने वाला फ़ंक्शन संकलन-समय के दौरान स्थापित किया जाता है।
- रनटाइम बहुरूपता में, लागू किया जाने वाला फ़ंक्शन रनटाइम के दौरान स्थापित किया जाता है।
- संकलन-समय बहुरूपता का निर्धारण फ़ंक्शन ओवरलोडिंग और ऑपरेटर ओवरलोडिंग के माध्यम से किया जाता है।
- फ़ंक्शन ओवरलोडिंग में, समान नाम वाले लेकिन अलग-अलग तर्क वाले कई फ़ंक्शन होते हैं।
- पैरामीटर संख्या या प्रकार में भिन्न हो सकते हैं।
- ऑपरेटर ओवरलोडिंग में, एक नया अर्थ परिभाषित किया गया है C++ ऑपरेटरों.
- रनटाइम बहुरूपता फ़ंक्शन ओवरराइडिंग के माध्यम से प्राप्त की जाती है।
- फ़ंक्शन ओवरराइडिंग में, व्युत्पन्न वर्ग आधार वर्ग में परिभाषित फ़ंक्शन को एक नई परिभाषा देता है।