C ++ में बहुरूपता


129

AFAIK:

सी ++ तीन अलग-अलग प्रकार के बहुरूपता प्रदान करता है।

  • आभासी कार्य
  • फंक्शन ओवरलोडिंग
  • ऑपरेटर ओवरलोडिंग

उपरोक्त तीन प्रकार के बहुरूपता के अलावा, अन्य प्रकार के बहुरूपता मौजूद हैं:

  • रन-टाइम
  • संकलन समय
  • तदर्थ बहुरूपता
  • पैरामीट्रिक बहुरूपता

मुझे पता है कि रनटाइम पोलिमोर्फ़िज्म को वर्चुअल फ़ंक्शंस द्वारा प्राप्त किया जा सकता है और स्टैटिक पॉलीमॉर्फिज़्म को टेम्पलेट फ़ंक्शंस द्वारा प्राप्त किया जा सकता है

लेकिन अन्य दो के लिए

तदर्थ बहुरूपता:

यदि वास्तविक प्रकारों का उपयोग किया जा सकता है, तो परिमित और संयोजनों को उपयोग करने से पहले व्यक्तिगत रूप से निर्दिष्ट किया जाना चाहिए, इसे तदर्थ बहुरूपता कहा जाता है।

पैरामीट्रिक बहुरूपता:

यदि सभी कोड किसी विशिष्ट प्रकार के उल्लेख के बिना लिखे गए हैं और इस प्रकार किसी भी प्रकार के नए प्रकार के साथ पारदर्शी रूप से इसका उपयोग किया जा सकता है तो इसे पैरामीट्रिक बहुरूपता कहा जाता है।

मैं शायद ही उन्हें समझ सकता हूँ :(

किसी को भी उन दोनों को समझा सकता है अगर एक उदाहरण के साथ संभव है? मुझे उम्मीद है कि इस प्रश्न के उत्तर उनके कॉलेजों के कई नए पासआउट के लिए उपयोगी होंगे।


30
दरअसल, C ++ में चार प्रकार के बहुरूपता हैं: पैरामीट्रिक (C ++ में टेम्प्लेट के माध्यम से उदारता), समावेशन (C ++ में वर्चुअल विधियों के माध्यम से घटाना), ओवरलोडिंग और ज़बरदस्ती (अंतर्निहित रूपांतरण)। अवधारणात्मक रूप से, फ़ंक्शन ओवरलोडिंग और ऑपरेटर ओवरलोडिंग के बीच थोड़ा अंतर है।
fredoverflow

तो ऐसा लगता है कि जिस वेबसाइट का मैंने उल्लेख किया है वह कई लोगों को भ्रमित कर रही है..मैं सही हूं?
विजय

@ ज़ोंबी: वह वेबसाइट बहुत सी अच्छी अवधारणाओं को छूती है, लेकिन शब्दावली के उपयोग में सटीक और सुसंगत नहीं है (उदाहरण के लिए, एक बार जब यह आभासी प्रेषण / रनटाइम बहुरूपता के बारे में बात करना शुरू करता है, तो यह बहुरूपता के बारे में बहुत कुछ बयान करता है जो गलत हैं सामान्य में लेकिन आभासी प्रेषण के लिए सच है)। यदि आप पहले से ही इस विषय को समझते हैं, तो आप जो कहा जा रहा है उससे संबंधित हो सकते हैं और मानसिक रूप से आवश्यक कैविएट सम्मिलित कर सकते हैं, लेकिन साइट को पढ़ने के लिए वहां जाना मुश्किल है ....
टोनी डेलरो

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

मैंने आपके लिए अपना फॉर्मेट तय कर दिया है। कृपया संपादन फलक के दाईं ओर उपलब्ध सहायता पढ़ें। > 200 प्रश्न और> 3k वाले किसी व्यक्ति को इस मूल सामग्री को जानना चाहिए। इसके अलावा, आप एक नया कीबोर्ड खरीदना चाहते हैं। लगता है कि यह एक शिफ्ट कुंजी इंटरफ़ेलिंग विफल हो रही है। ओह, और: C ++ में "टेम्पलेट फ़ंक्शन" जैसी कोई चीज नहीं है। हालांकि, फ़ंक्शन टेम्प्लेट हैं
sbi

जवाबों:


219

बहुरूपता के लिए / आवश्यकताओं की समझ

बहुरूपता को समझने के लिए - जैसा कि इस शब्द का उपयोग कम्प्यूटिंग साइंस में किया जाता है - यह इसके लिए एक सरल परीक्षा से शुरू करने में मदद करता है। विचार करें:

    Type1 x;
    Type2 y;

    f(x);
    f(y);

यहाँ, f()कुछ ऑपरेशन करना है और मान दिया जा रहा है xऔर yइनपुट के रूप में।

प्रदर्शनी बहुरूपता करने के लिए, f()कम से कम दो के मूल्यों के साथ काम करने में सक्षम होना चाहिए अलग प्रकार (उदाहरण के लिए intऔर double), खोजने और अलग प्रकार की दृष्टि से उचित कोड को क्रियान्वित।


बहुरूपता के लिए सी ++ तंत्र

स्पष्ट प्रोग्रामर-निर्दिष्ट बहुरूपता

आप ऐसा लिख f()सकते हैं कि यह निम्नलिखित में से किसी भी तरीके से कई प्रकारों पर काम कर सकता है:

  • preprocessing:

    #define f(X) ((X) += 2)
    // (note: in real code, use a longer uppercase name for a macro!)
  • ओवरलोडिंग:

    void f(int& x)    { x += 2; }
    
    void f(double& x) { x += 2; }
  • टेम्पलेट:

    template <typename T>
    void f(T& x) { x += 2; }
  • आभासी प्रेषण:

    struct Base { virtual Base& operator+=(int) = 0; };
    
    struct X : Base
    {
        X(int n) : n_(n) { }
        X& operator+=(int n) { n_ += n; return *this; }
        int n_;
    };
    
    struct Y : Base
    {
        Y(double n) : n_(n) { }
        Y& operator+=(int n) { n_ += n; return *this; }
        double n_;
    };
    
    void f(Base& x) { x += 2; } // run-time polymorphic dispatch

अन्य संबंधित तंत्र

कंपाइलर-प्रदत्त बहुरूपता के लिए निर्मित प्रकार, मानक रूपांतरण और कास्टिंग / जबरदस्ती के बारे में बाद में पूर्णता के लिए चर्चा की जाती है:

  • वे वैसे भी सहजता से समझ जाते हैं (" ओह, कि " प्रतिक्रिया "पर वारंट करते हुए)
  • वे उपर्युक्त तंत्रों और, का उपयोग करने में आवश्यकता और सीमा में प्रभाव को प्रभावित करते हैं
  • स्पष्टीकरण अधिक महत्वपूर्ण अवधारणाओं से एक काल्पनिक व्याकुलता है।

शब्दावली

आगे वर्गीकरण

उपरोक्त बहुरूपी तंत्र को देखते हुए, हम उन्हें विभिन्न तरीकों से वर्गीकृत कर सकते हैं:

  • पॉलीमॉर्फिक प्रकार-विशिष्ट कोड कब चुना जाता है?

    • रन टाइम का मतलब है कि कंपाइलर को सभी प्रकारों के लिए कोड तैयार करना होगा जो प्रोग्राम को चलाने के दौरान संभाल सकते हैं, और रन-टाइम में सही कोड का चयन किया जाता है ( वर्चुअल डिस्पैच )
    • संकलन समय का मतलब संकलन के दौरान टाइप-विशिष्ट कोड का चुनाव है। इसका एक परिणाम: केवल तर्कों के fसाथ ऊपर कहा गया एक कार्यक्रम कहें int- उपयोग किए गए पॉलीमॉर्फिक तंत्र पर निर्भर करता है और संकलक विकल्प संकलक के लिए किसी भी कोड को f(double)उत्पन्न करने से बच सकते हैं , या उत्पन्न कोड को संकलन या लिंकिंग में कुछ बिंदु पर फेंक दिया जा सकता है। ( आभासी प्रेषण को छोड़कर ऊपर के सभी तंत्र )

  • किस प्रकार समर्थित हैं?

    • एड-हॉक का अर्थ है कि आप प्रत्येक प्रकार (जैसे ओवरलोडिंग, टेम्पलेट विशेषज्ञता) का समर्थन करने के लिए स्पष्ट कोड प्रदान करते हैं; आप स्पष्ट रूप से "इसके लिए समर्थन" जोड़ते हैं (जैसा कि तदर्थ के अर्थ के अनुसार) प्रकार, कुछ अन्य "यह", और शायद "वह" भी ;-)।
    • पैरामीट्रिक का अर्थ है कि आप विशेष रूप से उनके लिए अपने समर्थन को सक्षम करने के लिए कुछ भी किए बिना विभिन्न पैरामीटर प्रकारों के लिए फ़ंक्शन का उपयोग करने का प्रयास कर सकते हैं (जैसे टेम्पलेट, मैक्रोज़)। कार्य / ऑपरेटरों के साथ एक वस्तु टेम्पलेट / मैक्रो उम्मीद की तरह कार्य है कि 1 है कि सभी सही प्रकार अप्रासंगिक होने के साथ अपना काम करने में टेम्पलेट / मैक्रो जरूरत है,। C ++ 20 द्वारा शुरू की गई "अवधारणाएं" ऐसी अपेक्षाओं को व्यक्त करती हैं और लागू करती हैं - यहाँ पर संक्षिप्तिकरण पृष्ठ देखें ।

      • पैरामीट्रिक बहुरूपता बतख टाइपिंग प्रदान करता है - एक अवधारणा जो जेम्स व्हिटकोम्ब रिले के लिए जिम्मेदार है जिसने स्पष्ट रूप से कहा "जब मैं एक पक्षी को देखता हूं जो बतख की तरह चलता है और बतख की तरह तैरता है और बतख की तरह झपटता है, तो मैं उस पक्षी को बतख कहता हूं।"

        template <typename Duck>
        void do_ducky_stuff(const Duck& x) { x.walk().swim().quack(); }
        
        do_ducky_stuff(Vilified_Cygnet());
    • उपप्रकार (उर्फ समावेशन) बहुरूपता आपको एल्गोरिथ्म / फ़ंक्शन को अपडेट किए बिना नए प्रकारों पर काम करने की अनुमति देता है, लेकिन उन्हें एक ही आधार वर्ग (आभासी प्रेषण) से प्राप्त किया जाना चाहिए

1 - टेम्प्लेट बेहद लचीले होते हैं। SFINAE (यह भी देखें std::enable_if) प्रभावी ढंग से पैरामीट्रिक बहुरूपता के लिए उम्मीदों के कई सेट की अनुमति देता है। उदाहरण के लिए, आप .size()यह समझ सकते हैं कि जब आप जिस प्रकार के डेटा को संसाधित कर रहे हैं, उसका एक सदस्य है तो आप एक फ़ंक्शन का उपयोग करेंगे, अन्यथा किसी अन्य फ़ंक्शन की आवश्यकता नहीं है .size()(लेकिन संभवतः किसी तरह से ग्रस्त है - जैसे कि धीमी का उपयोग करना strlen()या मुद्रण के रूप में नहीं। लॉग में उपयोगी संदेश)। जब आप विशिष्ट मापदंडों के साथ त्वरित किया जाता है तो आप तदर्थ व्यवहार भी निर्दिष्ट कर सकते हैं, या तो कुछ पैरामीटर पैरामीट्रिक ( आंशिक टेम्पलेट विशेषज्ञता ) या नहीं छोड़ना ( पूर्ण विशेषज्ञता )।

"बहुरूपी"

अल्फ स्टीनबाक टिप्पणी करता है कि सी ++ में मानक बहुरूपता केवल आभासी प्रेषण का उपयोग करके रन-टाइम बहुरूपता को संदर्भित करता है। सामान्य COMP। विज्ञान। C ++ निर्माता बज़्ने स्ट्रॉस्ट्रुप की शब्दावली ( http://www.stroustrup.com/glossary.html ) के अनुसार अर्थ अधिक समावेशी है :

बहुरूपता - विभिन्न प्रकार की संस्थाओं को एक एकल इंटरफ़ेस प्रदान करना। वर्चुअल फ़ंक्शंस एक बेस क्लास द्वारा दिए गए इंटरफ़ेस के माध्यम से गतिशील (रन-टाइम) बहुरूपता प्रदान करते हैं। अतिभारित कार्य और टेम्पलेट स्थैतिक (संकलन-समय) बहुरूपता प्रदान करते हैं। टीसी ++ पीएल 12.2.6, 13.6.1, डी एंड ई 2.9।

यह उत्तर - प्रश्न की तरह - COMP से C ++ सुविधाओं से संबंधित है। विज्ञान। शब्दावली।

विचार-विमर्श

C ++ मानक के साथ Comp की तुलना में "बहुरूपता" की एक संकीर्ण परिभाषा का उपयोग करते हुए। विज्ञान। समुदाय, अपने दर्शकों के लिए आपसी समझ सुनिश्चित करने के लिए ...

  • असंदिग्ध शब्दावली का उपयोग करते हुए ("क्या हम इस कोड को अन्य प्रकारों के लिए पुन: प्रयोज्य बना सकते हैं?" या "क्या हम वर्चुअल डिस्पैच का उपयोग कर सकते हैं?" के बजाय "क्या हम इस कोड को पॉलीमॉर्फिक बना सकते हैं?"), और / या
  • अपनी शब्दावली को स्पष्ट रूप से परिभाषित करना।

फिर भी, एक महान C ++ प्रोग्रामर होने के लिए क्या महत्वपूर्ण है यह समझना कि बहुरूपता वास्तव में आपके लिए क्या कर रहा है ...

    आपको एक बार "एल्गोरिथम" कोड लिखने की अनुमति देता है और फिर इसे कई प्रकार के डेटा पर लागू करता है

... और फिर इस बात से अवगत रहें कि विभिन्न पॉलिमर तंत्र आपकी वास्तविक जरूरतों से कैसे मेल खाते हैं।

रन-टाइम बहुरूपता सूट:

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

जब रन-टाइम बहुरूपता के लिए एक स्पष्ट ड्राइवर नहीं है, तो संकलन-समय विकल्प अक्सर बेहतर होते हैं। विचार करें:

  • टेम्प्लेटेड कक्षाओं का संकलन-व्हाट्स-तथाकथित पहलू रनटाइम में विफल वसा इंटरफेस के लिए बेहतर है
  • SFINAE
  • CRTP
  • अनुकूलन (कई इनलाइनिंग और डेड कोड एलिमिनेशन, लूप अनरोलिंग, स्टैटिक स्टैक-आधारित सरणियाँ बनाम ढेर)
  • __FILE__, __LINE__स्ट्रिंग शाब्दिक संयोजन और मैक्रोज़ की अन्य अनूठी क्षमताएं (जो बुराई बनी रहती हैं ;-))
  • टेम्प्लेट और मैक्रोज़ टेस्ट सिमेंटिक उपयोग समर्थित है, लेकिन कृत्रिम रूप से उस समर्थन को प्रतिबंधित नहीं किया जाता है (जैसा कि वर्चुअल डिस्पैच बिल्कुल मिलान सदस्य फ़ंक्शन ओवरराइड की आवश्यकता होती है)

बहुरूपता का समर्थन करने वाले अन्य तंत्र

जैसा कि वादा किया गया था, पूर्णता के लिए कई परिधीय विषय शामिल हैं:

  • संकलक-प्रदत्त अधिभार
  • रूपांतरण
  • डाले / बलात्कार

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

टाइपिंग-विशिष्ट संचालन के लिए मानचित्रण के लिए तंत्र

> जटिल संकलक-प्रदत्त ओवरलोड

वैचारिक रूप से, कंपाइलर बिलिन प्रकारों के लिए कई ऑपरेटरों को अधिभारित करता है। यह उपयोगकर्ता द्वारा निर्दिष्ट ओवरलोडिंग से वैचारिक रूप से भिन्न नहीं है, लेकिन इसे आसानी से अनदेखा किए जाने के रूप में सूचीबद्ध किया गया है। उदाहरण के लिए, आप एक ही संकेतन का उपयोग करके intएस और doubleएस जोड़ सकते हैं x += 2और संकलक का उत्पादन करता है:

  • प्रकार-विशिष्ट CPU निर्देश
  • उसी प्रकार का परिणाम है।

फिर ओवरलोडिंग उपयोगकर्ता-परिभाषित प्रकारों तक मूल रूप से फैलती है:

std::string x;
int y = 0;

x += 'c';
y += 'c';

उच्च-स्तरीय (3GL +) कंप्यूटर भाषाओं में मूल प्रकारों के लिए संकलक-प्रदान किए गए ओवरलोड आम हैं, और बहुरूपता की स्पष्ट चर्चा आम तौर पर कुछ और होती है। (2GLs - असेंबली लैंग्वेज - अक्सर प्रोग्रामर को स्पष्ट रूप से विभिन्न प्रकारों के लिए अलग-अलग mnemonics का उपयोग करने की आवश्यकता होती है।)

> मानक रूपांतरण

C ++ मानक का चौथा खंड मानक रूपांतरणों का वर्णन करता है।

पहला बिंदु संक्षेप में (एक पुराने मसौदे से - उम्मीद है कि अभी भी काफी हद तक सही है):

-1- मानक रूपांतरण अंतर्निहित रूपांतरण हैं जो अंतर्निहित प्रकारों के लिए परिभाषित किए गए हैं। खण्ड-खण्ड इस तरह के रूपांतरणों के पूर्ण सेट को दर्शाता है। एक मानक रूपांतरण अनुक्रम निम्नलिखित क्रम में मानक रूपांतरणों का एक क्रम है:

  • निम्नलिखित सेट से शून्य या एक रूपांतरण: lvalue-to-rvalue रूपांतरण, सरणी-से-पॉइंटर रूपांतरण और फ़ंक्शन-टू-पॉइंटर रूपांतरण।

  • निम्नलिखित सेट से शून्य या एक रूपांतरण: इंटीग्रल प्रमोशन, फ्लोटिंग पॉइंट प्रमोशन, इंटीग्रल कन्वर्सेशन, फ्लोटिंग पॉइंट कन्वर्सेशन, फ्लोटिंग-इंटीग्रल कन्वर्सेशन, पॉइंटर कन्वर्सेशन, मेम्बर टू मेम्बर कन्वर्जन और बुलियन कन्वर्सेशन।

  • शून्य या एक योग्यता रूपांतरण।

[नोट: एक मानक रूपांतरण अनुक्रम खाली हो सकता है, अर्थात, इसमें कोई रूपांतरण नहीं हो सकता है। ] आवश्यक गंतव्य प्रकार में परिवर्तित करने के लिए यदि आवश्यक हो तो एक मानक रूपांतरण अनुक्रम एक अभिव्यक्ति पर लागू किया जाएगा।

ये रूपांतरण कोड की अनुमति देते हैं जैसे:

double a(double x) { return x + 2; }

a(3.14);
a(42);

पहले के परीक्षण को लागू करना:

बहुरूपी होने के लिए, [ a()] कम से कम दो के मूल्यों के साथ काम करने में सक्षम होना चाहिए अलग प्रकार (उदाहरण के लिए intऔर double), खोजने और क्रियान्वित प्रकार उचित कोड

a()खुद के लिए विशेष रूप से कोड चलाता है doubleऔर इसलिए बहुरूपी नहीं है।

लेकिन, a()कंपाइलर को दूसरी कॉल में "फ्लोटिंग पॉइंट प्रमोशन" (स्टैंडर्ड to4) के लिए टाइप-उपयुक्त कोड जनरेट करना जानता 42है 42.0कॉलिंग फ़ंक्शन में वह अतिरिक्त कोड है । हम निष्कर्ष में इसके महत्व पर चर्चा करेंगे।

> ज़बरदस्ती, जातियां, निहित निर्माण

ये तंत्र उपयोगकर्ता-परिभाषित वर्गों को बिलिन प्रकार के मानक रूपांतरणों के समान व्यवहार को निर्दिष्ट करने की अनुमति देते हैं। चलो देखते हैं:

int a, b;

if (std::cin >> a >> b)
    f(a, b);

यहाँ, वस्तु std::cinका मूल्यांकन एक बूलियन संदर्भ में किया जाता है, रूपांतरण ऑपरेटर की सहायता से। यह वैचारिक रूप से उपरोक्त विषय में मानक रूपांतरणों से "अभिन्न प्रचार" एट अल के साथ समूहीकृत किया जा सकता है।

प्रभावी निर्माणकर्ता प्रभावी रूप से एक ही काम करते हैं, लेकिन कलाकारों द्वारा टाइप करने के लिए नियंत्रित होते हैं:

f(const std::string& x);
f("hello");  // invokes `std::string::string(const char*)`

संकलक-प्रदत्त अधिभार, रूपांतरण और जबरदस्ती के निहितार्थ

विचार करें:

void f()
{
    typedef int Amount;
    Amount x = 13;
    x /= 2;
    std::cout << x * 1.1;
}

यदि हम चाहते हैं कि राशि xको विभाजन के दौरान एक वास्तविक संख्या के रूप में माना जाए (अर्थात 6 से 6 के बजाय 6.5 हो), तो हम केवल परिवर्तन करते हैं typedef double Amount

यह अच्छा है, लेकिन यह कोड को स्पष्ट रूप से "प्रकार सही" बनाने के लिए बहुत अधिक काम नहीं होगा :

void f()                               void f()
{                                      {
    typedef int Amount;                    typedef double Amount;
    Amount x = 13;                         Amount x = 13.0;
    x /= 2;                                x /= 2.0;
    std::cout << double(x) * 1.1;          std::cout << x * 1.1;
}                                      }

लेकिन, विचार करें कि हम पहले संस्करण को एक में बदल सकते हैं template:

template <typename Amount>
void f()
{
    Amount x = 13;
    x /= 2;
    std::cout << x * 1.1;
}

यह उन छोटी "सुविधा सुविधाओं" के कारण है कि यह या तो आसानी से त्वरित रूप से तैयार की जा सकती है intया doubleइरादा के अनुसार काम कर सकती है । इन सुविधाओं के बिना, हमें स्पष्ट जाति, प्रकार के लक्षण और / या नीति वर्ग, कुछ क्रिया, त्रुटि-प्रवण गंदगी की आवश्यकता होगी:

template <typename Amount, typename Policy>
void f()
{
    Amount x = Policy::thirteen;
    x /= static_cast<Amount>(2);
    std::cout << traits<Amount>::to_double(x) * 1.1;
}

इसलिए, कंपाइलर प्रदान करने वाले ऑपरेटर बिलिन प्रकारों के लिए ओवरलोडिंग, मानक रूपांतरण, कास्टिंग / जबरदस्ती / निहित निर्माणकर्ता - ये सभी बहुरूपता के लिए सूक्ष्म समर्थन में योगदान करते हैं। इस उत्तर के शीर्ष पर परिभाषा से, वे मैपिंग के द्वारा "टाइप-उपयुक्त कोड को खोजने और निष्पादित करने" को संबोधित करते हैं:

  • पैरामीटर प्रकारों से "दूर"

    • से कई डेटा प्रकार बहुरूपी एल्गोरिथम कोड हैंडल

    • (संभावित रूप से कम) संख्या के लिए (समान या अन्य) प्रकारों के लिए लिखा गया कोड।

  • निरंतर प्रकार के मूल्यों से "टू" पैरामीट्रिक प्रकार

वे स्वयं द्वारा बहुरूपिक संदर्भों की स्थापना नहीं करते हैं, लेकिन ऐसे संदर्भों के अंदर कोड को सशक्त बनाने / सरल बनाने में सहायता करते हैं।

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

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


1
-1 महान शब्दावली शब्दावली चर्चा को छोड़कर। C ++ मानक "पॉलिमॉर्फिक" शब्द को .81.8 / 1 में परिभाषित करता है, जिसमें आभासी कार्यों के लिए धारा 10.3 का उल्लेख है। इसलिए कोई भी झगड़ा-कमरा नहीं है, चर्चा के लिए कोई जगह नहीं है, व्यक्तिगत राय के लिए कोई जगह नहीं है: मानक सी ++ के संदर्भ में यह शब्द एक बार और सभी के लिए परिभाषित किया गया है। और यह एक अभ्यास में खेलता है। उदाहरण के लिए, "5.2.7 / 6 के बारे dynamic_castमें " पॉलीमर या पॉलीमॉर्फिक प्रकार का एक संकेतक" की आवश्यकता होती है। चीयर्स एंड हथ।
चीयर्स एंड हथ। - अल्फ

@ शेल्फ: महान संदर्भ - हालांकि मुझे लगता है कि आपका दृष्टिकोण बहुत संकीर्ण है। यह ओवरलोडिंग, एड-हॉक और पैरामीट्रिक पॉलीमॉर्फिज्म इत्यादि पर सवाल करने वाली सूची से बहुत स्पष्ट है कि एक उत्तर को जनरल कंपास को C ++ की क्षमताओं से संबंधित होना चाहिए। विज्ञान। शब्दों का अर्थ। दरअसल, स्ट्रॉस्ट्रुप की शब्दावली कहती है, "बहुरूपता - विभिन्न प्रकारों की संस्थाओं को एक एकल इंटरफ़ेस प्रदान करना। वर्चुअल फ़ंक्शंस एक बेस क्लास द्वारा प्रदान किए गए इंटरफ़ेस के माध्यम से गतिशील (रन-टाइम) बहुरूपता प्रदान करते हैं। अतिभारित कार्यों और टेम्पलेट्स स्थिर (संकलन-समय) बहुरूपता। टीसी ++ पीएल 12.2.6, 13.6.1, डी एंड ई 2.9। "
टोनी डेलरो

@ टोनी: यह आपके जवाब का मुख्य जोर नहीं है गलत है। यह ठीक है, यह बहुत अच्छा है। यह सिर्फ उस wrt है। शब्दावली जो आपने इसे पीछे की ओर दिया है: औपचारिक अकादमिक शब्दावली पवित्र इंटरनेशनल स्टैंडर्ड द्वारा परिभाषित संकीर्ण एक है, और अनौपचारिक किसी न किसी शब्दावली का अर्थ है जहां लोगों को थोड़ा अलग चीजों का मतलब हो सकता है, मुख्य रूप से इस प्रश्न और उत्तर में उपयोग किया जाता है। चीयर्स एंड हथ।
चीयर्स एंड हथ। - अल्फ

@ शेल्फ: मैं चाहता हूं कि उत्तर महान थे - "अन्य तंत्र" को पांचवीं पंक्तियों में फिर से लिखने की आवश्यकता है, और मैं पॉलीमॉर्फिक तंत्र के विपरीत एक और अधिक ठोस सुविधाओं और निहितार्थों पर विचार / मसौदा तैयार कर रहा हूं। वैसे भी, मेरी समझ यह है कि औपचारिक अकादमिक विशेष रूप से सी-++ - केंद्रित अर्थ संकीर्ण हो सकता है, लेकिन औपचारिक अकादमिक जनरल कॉम्प। विज्ञान। अर्थ यह नहीं है, जैसा कि स्ट्रॉस्ट्रुप की शब्दावली से स्पष्ट है। हमें कुछ निश्चित की जरूरत है - जैसे कि नथ से परिभाषा - कोई भाग्य अभी तक नहीं है। मैं सराहना करता हूं कि आप एक C ++ गुरु हैं, लेकिन क्या आप इस पर विशेष रूप से प्रासंगिक प्रमाणों की ओर संकेत कर सकते हैं?
टोनी डेलारॉय

1
@ शेल्फ: दूसरी बात, मुझे विश्वास है कि बहुरूपता को औपचारिक रूप से किसी भी सामान्य सामान्य कंप्यूटर में परिभाषित किया गया है। विज्ञान। मेरे उपयोग (और स्ट्रॉस्ट्रुप) के साथ संगत समयबद्ध (स्थिर, स्थिर) तरीके से पुस्तक। विकिपीडिया लेख कुछ अकादमिक प्रकाशनों को जोड़ता है जो इसे इस तरह परिभाषित करते हैं: "बहुरूपिक कार्य ऐसे कार्य हैं जिनके ऑपरेंड (वास्तविक पैरामीटर) में एक से अधिक प्रकार हो सकते हैं। बहुरूपिक प्रकार वे प्रकार होते हैं जिनके संचालन एक से अधिक प्रकारों के मूल्यों पर लागू होते हैं।" ( lucacardelli.name/Papers/OnUnderstanding.A4.pdf से )। तो, सवाल यह है कि "कॉम्प साइंस के लिए कौन बोलता है" ...?
टोनी डेलारॉय

15

C ++ में, महत्वपूर्ण अंतर रन-टाइम बनाम संकलन-टाइम बाइंडिंग है। जैसा कि मैं बाद में समझाता हूँ, तदर्थ बनाम पैरामीट्रिक वास्तव में मदद नहीं करता है।

|----------------------+--------------|
| Form                 | Resolved at  |
|----------------------+--------------|
| function overloading | compile-time |
| operator overloading | compile-time |
| templates            | compile-time |
| virtual methods      | run-time     |
|----------------------+--------------|

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

फंक्शन ओवरलोडिंग और ऑपरेटर ओवरलोडिंग हर तरह से एक ही चीज है जो मायने रखती है। नाम और उन्हें उपयोग करने के लिए वाक्यविन्यास बहुरूपता को प्रभावित नहीं करता है।

टेम्पलेट्स आपको एक ही बार में बहुत सारे फ़ंक्शन ओवरलोड निर्दिष्ट करने की अनुमति देते हैं।

एक ही संकल्प-समय विचार के लिए नामों का एक और सेट है ...

|---------------+--------------|
| early binding | compile-time |
| late binding  | run-time     |
|---------------+--------------|

ये नाम ओओपी के साथ अधिक जुड़े हुए हैं, इसलिए यह कहना थोड़ा अजीब है कि एक टेम्पलेट या अन्य गैर-सदस्यीय फ़ंक्शन जल्दी बाध्यकारी का उपयोग करता है।

वर्चुअल फ़ंक्शंस और फ़ंक्शन ओवरलोडिंग के बीच संबंधों को बेहतर ढंग से समझने के लिए, "एकल प्रेषण" और "एकाधिक प्रेषण" के बीच के अंतर को समझना उपयोगी है। विचार को प्रगति के रूप में समझा जा सकता है ...

  • सबसे पहले, मोनोमोर्फिक फ़ंक्शन हैं। फ़ंक्शन का कार्यान्वयन फ़ंक्शन नाम से विशिष्ट रूप से पहचाना जाता है। कोई भी पैरामीटर विशेष नहीं है।
  • फिर, वहाँ एक प्रेषण है। मापदंडों में से एक विशेष माना जाता है, और इसका उपयोग (नाम के साथ) यह पहचानने के लिए कि किस कार्यान्वयन का उपयोग करना है। OOP में, हम इस पैरामीटर को "ऑब्जेक्ट" के रूप में सोचते हैं, इसे फ़ंक्शन नाम आदि से पहले सूचीबद्ध करते हैं।
  • फिर, कई प्रेषण है। किसी भी / सभी मापदंडों का उपयोग करने के लिए कौन से कार्यान्वयन की पहचान करने में योगदान करते हैं। इसलिए, एक बार फिर, किसी भी पैरामीटर को विशेष होने की आवश्यकता नहीं है।

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

जिस तरह गैर-सदस्य कार्यों के लिए "शुरुआती बंधन" शब्द का उपयोग करना थोड़ा अजीब है, "संकलक" और "एकाधिक प्रेषण" शब्दों का उपयोग करना थोड़ा अजीब है, जहां संकलन के समय बहुरूपता का समाधान किया जाता है। आमतौर पर, C ++ को कई प्रेषण नहीं माना जाता है, जिसे एक विशेष प्रकार का रन-टाइम रिज़ॉल्यूशन माना जाता है। हालाँकि, फ़ंक्शन ओवरलोडिंग को संकलन-समय पर किए गए कई-प्रेषण के रूप में देखा जा सकता है।

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

पैरामीट्रिक पॉलीमॉर्फिज्म का मतलब है कि आपके पास पैरामीटर के रूप में प्रकार हैं, और सटीक समान कोड का उपयोग किया जाता है, भले ही आप उन मापदंडों के लिए किस प्रकार का उपयोग करते हों।

एड-हॉक बहुरूपता इस अर्थ में तदर्थ है कि आप विशेष प्रकार के आधार पर अलग-अलग कोड प्रदान करते हैं।

ओवरलोडिंग और वर्चुअल फ़ंक्शंस एड-हॉक बहुरूपता के दोनों उदाहरण हैं।

फिर से, कुछ पर्यायवाची हैं ...

|------------+---------------|
| parametric | unconstrained |
| ad-hoc     | constrained   |
|------------+---------------|

सिवाय इन के पर्यायवाची पर्यायवाची शब्द नहीं हैं, हालाँकि वे आमतौर पर वैसे ही माने जाते हैं जैसे वे थे, और यहीं से सी ++ में भ्रम पैदा होने की संभावना है।

इनको पर्यायवाची मानने के पीछे तर्क यह है कि विशेष प्रकार के वर्गों के बहुरूपता को विवश करके, उन प्रकारों के विशिष्ट वर्गों के लिए संचालन का उपयोग करना संभव हो जाता है। यहां "कक्षाएं" शब्द की व्याख्या ओओपी अर्थों में की जा सकती है, लेकिन वास्तव में केवल कुछ प्रकार के कार्यों को साझा करने वाले प्रकारों के सेट (आमतौर पर नामित) को संदर्भित करता है।

तो पैरामीट्रिक बहुरूपता को आमतौर पर (कम से कम डिफ़ॉल्ट रूप से) अप्रतिबंधित बहुरूपता से लिया जाता है। चूँकि समान मापदंडों के बावजूद समान कोड का उपयोग किया जाता है, केवल सहायक संचालन वे होते हैं जो सभी प्रकारों के लिए काम करते हैं। असंबंधित प्रकार के सेट को छोड़कर, आप उन प्रकारों पर लागू किए जाने वाले संचालन के सेट को गंभीर रूप से सीमित कर सकते हैं।

जैसे हास्केल में, आप कर सकते हैं ...

myfunc1 :: Bool -> a -> a -> a
myfunc1 c x y = if c then x else y

aयहाँ एक स्वेच्छापूर्ण बहुरूपी प्रकार है। यह कुछ भी हो सकता है, इसलिए हम उस प्रकार के मूल्यों के साथ बहुत कुछ नहीं कर सकते हैं।

myfunc2 :: Num a => a -> a
myfunc2 x = x + 3

यहाँ, वर्ग aका सदस्य बनने के लिए विवश है Num- प्रकार जो संख्याओं की तरह कार्य करते हैं। यह बाधा आपको उन मूल्यों के साथ नंबर-ईश चीजों को करने की अनुमति देती है, जैसे कि उन्हें जोड़ें। यहां तक ​​कि 3बहुरूपता है - प्रकार के अनुमानों से पता चलता है कि आपका मतलब 3प्रकार का है a

मैं इस पर विवश पैरामीट्रिक बहुरूपता के रूप में सोचता हूं। केवल एक कार्यान्वयन है, लेकिन यह केवल विवश मामलों में ही लागू किया जा सकता है। एड-हॉक पहलू किसकी पसंद है +और 3किसका उपयोग करना है। प्रत्येक "उदाहरण" Numका इनका अपना अलग कार्यान्वयन है। तो हास्केल में भी "पैरामीट्रिक" और "असंबद्ध" वास्तव में समानार्थी शब्द नहीं हैं - मुझे दोष मत दो, यह मेरी गलती है!

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

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

तो एक तरह से C ++ में पैरामीट्रिक पॉलीमॉर्फिज़्म है, लेकिन यह स्पष्ट रूप से विवश है और तदर्थ विकल्प द्वारा ओवरराइड किया जा सकता है - यानी यह वर्गीकरण वास्तव में C ++ के लिए काम नहीं करता है।


दिलचस्प बिंदुओं और अंतर्दृष्टि के +1। मैंने केवल हास्केल के बारे में पढ़ने में कुछ घंटे बिताए हैं, इसलिए " aयहाँ एक असंसाधित बहुरूपी प्रकार है [...] इसलिए हम उस प्रकार के मूल्यों के साथ बहुत कुछ नहीं कर सकते हैं।" रुचि थी - C ++ sans अवधारणाओं में आप केवल एक टेम्प्लेट पैरामीटर के रूप में निर्दिष्ट एक प्रकार के तर्क पर संचालन के एक विशिष्ट सेट का प्रयास करने के लिए प्रतिबंधित नहीं हैं ... लाइब्रेरी जैसे बूस्ट कॉन्सेप्ट दूसरे तरीके से काम करते हैं - यह सुनिश्चित करता है कि प्रकार संचालन का समर्थन करता है आप अतिरिक्त कार्यों के आकस्मिक उपयोग के खिलाफ रक्षा करने के बजाय निर्दिष्ट करते हैं।
टोनी डेलारॉय

@ टॉनी - कॉन्सेप्ट एक तरह से टेम्प्लेट के बहुरूपता को विवश करने का तरीका है। अंतर्निहित बाधाएं स्पष्ट रूप से संगतता के कारण दूर नहीं जाएंगी, लेकिन स्पष्ट बाधाओं से निश्चित रूप से चीजों में काफी सुधार होगा। मुझे पूरा यकीन है कि अवधारणाओं के लिए कुछ पिछली योजनाएं हास्केल टाइपकालेज़ से कुछ हद तक संबंधित थीं, हालांकि मैंने उन पर ध्यान नहीं दिया था और जब मैंने आखिरी बार "उथलेपन" को देखा तो मुझे ज्यादा हास्केल नहीं पता था।
स्टीव 314

"अंतर्निहित बाधाएं स्पष्ट रूप से संगतता के कारण दूर नहीं जाएंगी" - स्मृति से, C ++ 0x अवधारणाओं ने किया (वादा: - / /) "निहित बाधाओं" को रोकने के लिए - आप केवल अवधारणाओं के द्वारा वादा किए गए तरीकों से प्रकार का उपयोग कर सकते हैं।
टोनी डेलरो

2

तदर्थ बहुरूपता के रूप में, इसका अर्थ है फ़ंक्शन ओवरलोडिंग या ऑपरेटर ओवरलोडिंग। यहां देखें:

http://en.wikipedia.org/wiki/Ad-hoc_polymorphism

पैरामीट्रिक बहुरूपता के रूप में, टेम्पलेट कार्यों को भी गिना जा सकता है क्योंकि वे आवश्यक रूप से FIXED प्रकार के मापदंडों में नहीं लेते हैं। उदाहरण के लिए, एक फ़ंक्शन पूर्णांक के सरणी को सॉर्ट कर सकता है और यह स्ट्रिंग के सरणी को भी सॉर्ट कर सकता है, आदि।

http://en.wikipedia.org/wiki/Parametric_polymorphism


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

वास्तव में आपका उदाहरण - छांटना - एक बाधा का अर्थ है। क्रमबद्ध करने के लिए केवल उन प्रकारों के लिए काम करता है जो ऑर्डर किए गए हैं (जैसे <और समान ऑपरेटर प्रदान करते हैं )। हास्केल में, आप स्पष्ट रूप से कक्षा का उपयोग करके उस आवश्यकता को व्यक्त करेंगे Ord। तथ्य यह है कि आप एक <विशेष प्रकार (उदाहरण के द्वारा आपूर्ति की गई Ord) के आधार पर अलग - अलग हो जाते हैं, को तदर्थ बहुरूपता माना जाएगा।
स्टीव ३४

2

यह किसी भी मदद का नहीं हो सकता है, लेकिन मैंने इसे अपने दोस्तों को प्रोग्रामिंग के लिए निर्धारित कार्यों, जैसे START, और ENDमुख्य कार्य के लिए पेश करने के लिए बनाया है इसलिए यह बहुत कठिन नहीं था (वे केवल main.cpp फ़ाइल का उपयोग करते थे )। इसमें पॉलीमॉर्फिक कक्षाएं और संरचनाएं, टेम्प्लेट, वैक्टर, एरेज़, प्रीप्रोसेसर निर्देश, दोस्ती, ऑपरेटर और पॉइंटर्स शामिल हैं (यह सब आपको शायद बहुरूपता का प्रयास करने से पहले पता होना चाहिए):

नोट: यह समाप्त नहीं हुआ है, लेकिन आप विचार प्राप्त कर सकते हैं

main.cpp

#include "main.h"
#define ON_ERROR_CLEAR_SCREEN false
START
    Library MyLibrary;
    Book MyBook("My Book", "Me");
    MyBook.Summarize();
    MyBook += "Hello World";
    MyBook += "HI";
    MyBook.EditAuthor("Joe");
    MyBook.EditName("Hello Book");
    MyBook.Summarize();
    FixedBookCollection<FairyTale> FBooks("Fairytale Books");
    FairyTale MyTale("Tale", "Joe");
    FBooks += MyTale;
    BookCollection E("E");
    MyLibrary += E;
    MyLibrary += FBooks;
    MyLibrary.Summarize();
    MyLibrary -= FBooks;
    MyLibrary.Summarize();
    FixedSizeBookCollection<5> Collection("My Fixed Size Collection");
    /* Extension Work */ Book* Duplicate = MyLibrary.DuplicateBook(&MyBook);
    /* Extension Work */ Duplicate->Summarize();
END

main.h

#include <iostream>
#include <sstream>
#include <vector>
#include <string>
#include <type_traits>
#include <array>
#ifndef __cplusplus
#error Not C++
#endif
#define START int main(void)try{
#define END GET_ENTER_EXIT return(0);}catch(const std::exception& e){if(ON_ERROR_CLEAR_SCREEN){system("cls");}std::cerr << "Error: " << e.what() << std::endl; GET_ENTER_EXIT return (1);}
#define GET_ENTER_EXIT std::cout << "Press enter to exit" << std::endl; getchar();
class Book;
class Library;
typedef std::vector<const Book*> Books;
bool sContains(const std::string s, const char c){
    return (s.find(c) != std::string::npos);
}
bool approve(std::string s){
    return (!sContains(s, '#') && !sContains(s, '%') && !sContains(s, '~'));
}
template <class C> bool isBook(){
    return (typeid(C) == typeid(Book) || std::is_base_of<Book, C>());
}
template<class ClassToDuplicate> class DuplicatableClass{ 
public:
    ClassToDuplicate* Duplicate(ClassToDuplicate ToDuplicate){
        return new ClassToDuplicate(ToDuplicate);
    }
};
class Book : private DuplicatableClass<Book>{
friend class Library;
friend struct BookCollection;
public:
    Book(const char* Name, const char* Author) : name_(Name), author_(Author){}
    void operator+=(const char* Page){
        pages_.push_back(Page);
    }
    void EditAuthor(const char* AuthorName){
        if(approve(AuthorName)){
            author_ = AuthorName;
        }
        else{
            std::ostringstream errorMessage;
            errorMessage << "The author of the book " << name_ << " could not be changed as it was not approved";
            throw std::exception(errorMessage.str().c_str());
        }
    }
    void EditName(const char* Name){
        if(approve(Name)){
            name_ = Name;
        }
        else{
            std::ostringstream errorMessage;
            errorMessage << "The name of the book " << name_ << " could not be changed as it was not approved";
            throw std::exception(errorMessage.str().c_str());
        }
    }
    virtual void Summarize(){
        std::cout << "Book called " << name_ << "; written by " << author_ << ". Contains "
            << pages_.size() << ((pages_.size() == 1) ? " page:" : ((pages_.size() > 0) ? " pages:" : " pages")) << std::endl;
        if(pages_.size() > 0){
            ListPages(std::cout);
        }
    }
private:
    std::vector<const char*> pages_;
    const char* name_;
    const char* author_;
    void ListPages(std::ostream& output){
        for(int i = 0; i < pages_.size(); ++i){
            output << pages_[i] << std::endl;
        }
    }
};
class FairyTale : public Book{
public:
    FairyTale(const char* Name, const char* Author) : Book(Name, Author){}
};
struct BookCollection{
friend class Library;
    BookCollection(const char* Name) : name_(Name){}
    virtual void operator+=(const Book& Book)try{
        Collection.push_back(&Book); 
    }catch(const std::exception& e){
        std::ostringstream errorMessage;
        errorMessage << e.what() << " - on line (approx.) " << (__LINE__ -3);
        throw std::exception(errorMessage.str().c_str());
    }
    virtual void operator-=(const Book& Book){
        for(int i = 0; i < Collection.size(); ++i){
            if(Collection[i] == &Book){
                Collection.erase(Collection.begin() + i);
                return;
            }
        }
        std::ostringstream errorMessage;
        errorMessage << "The Book " << Book.name_ << " was not found, and therefore cannot be erased";
        throw std::exception(errorMessage.str().c_str());
    }
private:
    const char* name_;
    Books Collection;
};
template<class FixedType> struct FixedBookCollection : public BookCollection{
    FixedBookCollection(const char* Name) : BookCollection(Name){
        if(!isBook<FixedType>()){
            std::ostringstream errorMessage;
            errorMessage << "The type " << typeid(FixedType).name() << " cannot be initialized as a FixedBookCollection";
            throw std::exception(errorMessage.str().c_str());
            delete this;
        }
    }
    void operator+=(const FixedType& Book)try{
        Collection.push_back(&Book); 
    }catch(const std::exception& e){
        std::ostringstream errorMessage;
        errorMessage << e.what() << " - on line (approx.) " << (__LINE__ -3);
        throw std::exception(errorMessage.str().c_str());
    }
    void operator-=(const FixedType& Book){
        for(int i = 0; i < Collection.size(); ++i){
            if(Collection[i] == &Book){
                Collection.erase(Collection.begin() + i);
                return;
            }
        }
        std::ostringstream errorMessage;
        errorMessage << "The Book " << Book.name_ << " was not found, and therefore cannot be erased";
        throw std::exception(errorMessage.str().c_str());
    }
private:
    std::vector<const FixedType*> Collection;
};
template<size_t Size> struct FixedSizeBookCollection : private std::array<const Book*, Size>{
    FixedSizeBookCollection(const char* Name) : name_(Name){ if(Size < 1){ throw std::exception("A fixed size book collection cannot be smaller than 1"); currentPos = 0; } }
    void operator+=(const Book& Book)try{
        if(currentPos + 1 > Size){
            std::ostringstream errorMessage;
            errorMessage << "The FixedSizeBookCollection " << name_ << "'s size capacity has been overfilled";
            throw std::exception(errorMessage.str().c_str());
        }
        this->at(currentPos++) = &Book;
    }catch(const std::exception& e){
        std::ostringstream errorMessage;
        errorMessage << e.what() << " - on line (approx.) " << (__LINE__ -3);
        throw std::exception(errorMessage.str().c_str());
    }
private:
    const char* name_;
    int currentPos;
};
class Library : private std::vector<const BookCollection*>{
public:
    void operator+=(const BookCollection& Collection){
        for(int i = 0; i < size(); ++i){
            if((*this)[i] == &Collection){
                std::ostringstream errorMessage;
                errorMessage << "The BookCollection " << Collection.name_ << " was already in the library, and therefore cannot be added";
                throw std::exception(errorMessage.str().c_str());
            }
        }
        push_back(&Collection);
    }
    void operator-=(const BookCollection& Collection){
        for(int i = 0; i < size(); ++i){
            if((*this)[i] == &Collection){
                erase(begin() + i);
                return;
            }
        }
        std::ostringstream errorMessage;
        errorMessage << "The BookCollection " << Collection.name_ << " was not found, and therefore cannot be erased";
        throw std::exception(errorMessage.str().c_str());
    }
    Book* DuplicateBook(Book* Book)const{
        return (Book->Duplicate(*Book));
    }
    void Summarize(){
        std::cout << "Library, containing " << size() << ((size() == 1) ? " book collection:" : ((size() > 0) ? " book collections:" : " book collections")) << std::endl;
        if(size() > 0){
            for(int i = 0; i < size(); ++i){
                std::cout << (*this)[i]->name_ << std::endl;
            }
        }
    }
};

1

यहां पॉलिमॉर्फिक कक्षाओं का उपयोग करके एक मूल उदाहरण दिया गया है

#include <iostream>

class Animal{
public:
   Animal(const char* Name) : name_(Name){/* Add any method you would like to perform here*/
    virtual void Speak(){
        std::cout << "I am an animal called " << name_ << std::endl;
    }
    const char* name_;
};

class Dog : public Animal{
public:
    Dog(const char* Name) : Animal(Name) {/*...*/}
    void Speak(){
        std::cout << "I am a dog called " << name_ << std::endl;
    }
};

int main(void){
    Animal Bob("Bob");
    Dog Steve("Steve");
    Bob.Speak();
    Steve.Speak();
    //return (0);
}

0

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


-3

अगर कोई इन लोगों को CUT कहता है

The Surgeon
The Hair Stylist
The Actor

क्या होगा?

The Surgeon would begin to make an incision.
The Hair Stylist would begin to cut someone's hair.
The Actor would abruptly stop acting out of the current scene, awaiting directorial guidance.

तो उपरोक्त प्रतिनिधित्व से पता चलता है कि ओओपी में बहुरूपता (एक ही नाम, अलग व्यवहार) क्या है।

यदि आप एक साक्षात्कार के लिए जा रहे हैं और साक्षात्कारकर्ता आपसे पूछता है कि हम जिस कमरे में बैठे हैं, उसी कमरे में बहुरूपता के लिए एक जीवंत उदाहरण बताएं / दिखाएं-

उत्तर - द्वार / विंडोज

आश्चर्य है कि कैसे?

डोर / विंडो के माध्यम से - एक व्यक्ति आ सकता है, हवा आ सकती है, प्रकाश आ सकता है, बारिश आ सकती है, आदि।

अर्थात एक अलग व्यवहार (बहुरूपता)।

इसे बेहतर तरीके से समझने के लिए और सरल तरीके से मैंने ऊपर दिए गए उदाहरण का उपयोग किया है .. यदि आपको उत्तर के लिए कोड अनुसरण के लिए संदर्भ की आवश्यकता है।


जैसा कि मैंने c ++ में Polymorphism की बेहतर समझ के लिए उल्लेख किया है, मैंने ऊपर दिए गए उदाहरण का उपयोग किया है। यह एक नवसिखुआ को वास्तव में समझने और संबंधित होने में मदद कर सकता है कि साक्षात्कार में प्रदर्शन करते समय कोड के पीछे क्या अर्थ है या क्या हो रहा है। धन्यवाद!
संचित

op ने पूछा "c ++ में बहुरूपता"। आपका जवाब भी बहुत सार है।
StahlRat
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.