2012-01-23 16 views
16

साथ एक सदस्य समारोह ओवरराइड नीचे दिए गए उदाहरण पर विचार करें। व्युत्पन्न कक्षा में एक अलग रिटर्न प्रकार के साथ किसी फ़ंक्शन को ओवरराइड करना क्यों संभव नहीं है?अलग वापसी प्रकार

मेरा मानना ​​है कि, किसी फ़ंक्शन को ओवरराइड करने के क्रम में, बेस क्लास वर्चुअल विधि को व्युत्पन्न कक्षा में फिर से परिभाषित करने की आवश्यकता है। किसी विधि को फिर से परिभाषित करने के लिए, विधियों के हस्ताक्षर समान होना चाहिए। चूंकि वापसी का प्रकार हस्ताक्षर का हिस्सा नहीं है, इसलिए मेरा मानना ​​है कि रिटर्न प्रकार में अंतर होने पर भी, विधि को फिर से परिभाषित किया जाएगा? उस मामले में उपर्युक्त कोड के लिए, वर्चुअल फ़ंक्शन func व्युत्पन्न कक्षा में एक अलग रिटर्न प्रकार के साथ फिर से परिभाषित किया गया है। लेकिन संकलक एक त्रुटि फेंकता है। क्या मेरी समझ सही है?

+0

स्पष्टीकरण के लिए, क्या संकलक आप दे रहा है क्या त्रुटि है? –

+0

@ सियोनशेवोक, जीसीसी कम से कम करता है: http://codepad.org/z7rXpCeK – bdonlan

+0

@ सियोनशेवोक: मैं जीसीसी 3.4.6 –

उत्तर

17

ओवरराइडिंग का अर्थ यह है कि बेस क्लास विधि या व्युत्पन्न वर्ग विधि को पॉइंटर द्वारा इंगित वास्तविक वस्तु के आधार पर रन-टाइम पर कॉल किया जाएगा ।
इसका तात्पर्य है कि:
i.e: बेस क्लास विधि को कॉल करने के लिए हर जगह जहां कॉलिंग कोड में किसी भी बदलाव के बिना व्युत्पन्न क्लास विधि को कॉल करके प्रतिस्थापित किया जा सकता है।

यह प्राप्त करने के लिए ओवरराइडिंग वर्चुअल विधियों के रिटर्न प्रकारों को बेस क्लास या उस प्रकार से प्राप्त एक प्रकार (सह-संस्करण वापसी प्रकार) और मानक लागू करने के लिए एकमात्र संभावित तरीका प्रतिबंधित करना है। यह स्थिति।

यदि उपर्युक्त स्थिति जगह पर नहीं थी तो यह नई कार्यक्षमता के अतिरिक्त मौजूदा कोड को तोड़ने के लिए एक विंडो छोड़ देगा।

+2

अलस: 'उस प्रकार से प्राप्त प्रकार (सह-प्रकार वापसी प्रकार) '। यह मेरी समझ के लिए महत्वपूर्ण था। अच्छा स्पष्टीकरण। :) –

7

वर्चुअल फ़ंक्शन को ओवरराइड करने के लिए, वापसी मान बिल्कुल वही होना चाहिए *। सी ++ स्वचालित रूप से double और int के बीच कनवर्ट करेगा - आखिरकार, यह कैसे पता चलेगा कि व्युत्पन्न क्लास पॉइंटर से कॉल करते समय आप किस प्रकार का रिटर्न टाइप चाहते हैं? ध्यान दें कि यदि आप हस्ताक्षर (पैरामीटर, कॉन्स्ट-नेस, आदि) का हिस्सा बदलते हैं, तो आप रिटर्न वैल्यू भी बदल सकते हैं।

* - सख्ती से बोलना, यह 'covariant' होना चाहिए। इसका अर्थ यह है कि जिस प्रकार आप लौटते हैं वह मूल कार्य के रिटर्न प्रकार का सबसेट होना चाहिए। उदाहरण के लिए, यदि अभिभावक वर्ग base * देता है, तो आप derived * वापस कर सकते हैं। चूंकि derived एस एक साथ base एस हैं, इसलिए कंपाइलर आपको इस तरीके से ओवरराइड करने देता है। लेकिन आप int और double जैसे पूरी तरह से असंबंधित प्रकार वापस नहीं कर सकते; सिर्फ इसलिए कि एक अंतर्निहित रूपांतरण है इसका मतलब यह नहीं है कि संकलक आपको इस तरह के ओवरराइड करने देगा।

+0

'ध्यान दें कि यदि आप हस्ताक्षर (पैरामीटर, कॉन्स्ट-नेस, आदि) का हिस्सा बदलते हैं, तो आप रिटर्न वैल्यू को भी बदल सकते हैं। अगर मैं ऐसा करता हूं तो फ़ंक्शन सही नहीं हो जाता है? –

+3

बिल्कुल वही या सबक्लास, मुझे लगता है कि आपका मतलब है। वर्चुअल फ़ंक्शंस के लिए – Nemo

+1

'सह-संस्करण' रिटर्न प्रकारों की अनुमति है। –

1

this question देखें। संक्षेप में, यदि आप covariant प्रकार हैं तो आप एक अलग रिटर्न प्रकार का उपयोग करके केवल वर्चुअल फ़ंक्शन को ओवरराइड कर सकते हैं।

+0

* प्रकार * कॉन्वेंट नहीं हैं, * ओवरराइड * है। –

+0

क्या मैं कैसे जुड़ा हुआ अर्थशास्त्र को गलत समझता है? – ezod

+0

नहीं, केवल इसकी व्याख्या ही थोड़ी मूर्खतापूर्ण है। –

0

ओवरराइडिंग संभव नहीं है, क्योंकि हस्ताक्षर अलग हैं। ओवरराइडिंग का मूल उद्देश्य बहुरूपता है लेकिन उपर्युक्त उदाहरण

+1

हस्ताक्षर यहां समान हैं। कार्य केवल रिटर्न प्रकार में भिन्न होते हैं और वापसी प्रकार हस्ताक्षर का हिस्सा नहीं है। –

+0

@LinuxPenseur कहने के लिए धन्यवाद, यही मेरा इरादा है कि – kvk

1

यदि आप ओवरराइड करना चाहते हैं, तो आपको टेम्पलेट का उपयोग करने का प्रयास करना चाहिए।

निम्नलिखित देखें:

#include <iostream> 

using namespace std; 

class base 
{ 
    public: 
     template<typename X> X func() 
     { 
     cout << "vfunc in base class\n"; 
     return static_cast<X>(0); 
     } 
};  

class derived: public base 
{ 
    public: 
     template<typename X> X func() 
     { 
     cout << "vfunc in derived class\n"; 
     return static_cast<X>(2); 
     } 
};  

int main() 
{ 
    derived *bptr = new derived; 
    cout << bptr->func<int>() << endl; 
    cout << dynamic_cast<base*>(bptr)->func<int>() << endl; 

    derived *bptr2 = new derived; 
    cout << bptr->func<double>() << endl; 
    cout << dynamic_cast<base*>(bptr)->func<int>() << endl; 


    return 0; 
} 
बेशक

, आप न दो अलग-अलग वर्ग है कि रास्ते में यह घोषणा करने की जरूरत है, तुम कर सकते हो:

class base 
{ 
    public: 
     int func() 
     { 
     cout << "vfunc in base class\n"; 
     return 0; 
     } 

     double func(){ 
     cout << "vfunc for double class\n"; 
     return 2.; 

     } 
}; 
संबंधित मुद्दे