2015-06-17 9 views
14

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

जावा संस्करण:

class base{ 
    public void func1(){ 
     func2(); 
    } 
    public void func2(){ 
     System.out.println(" I am in base:func2() \n"); 
    } 

} 

class derived extends base{ 
    public void func1(){ 
     super.func1(); 
    } 
    public void func2(){ 
     System.out.println(" I am in derived:func2() \n"); 
    } 
}; 
public class Test 
{ 
    public static void main(String[] args){ 
     derived d = new derived(); 
     d.func1(); 
    } 
} 

उत्पादन:

I am in derived:func2() 

सी ++ संस्करण:

#include <stdio.h> 

class base 
{ 
    public: 
     void func1(){ 
      func2(); 
     } 
     void func2(){ 
      printf(" I am in base:func2() \n"); 
     } 
}; 

class derived : public base 
{ 
    public: 
     void func1(){ 
      base::func1(); 
     } 
     void func2(){ 
      printf(" I am in derived:func2() \n"); 
     } 
}; 

int main() 
{ 
    derived *d = new derived(); 
    d->func1(); 
    return 0; 
} 

उत्पादन:

I am in base:func2() 

मुझे नहीं पता कि उनके पास अलग-अलग व्यवहार क्यों हैं।

यहां तक ​​कि मुझे पता है कि जावा में ऑटो पॉलिमॉर्फिज्म व्यवहार है।

जावा आउटपुट व्यक्तिगत रूप से समझना मुश्किल है।

मेरी नजर में, static scope के अनुसार, आधार वर्ग समारोह func1() केवल, आधार वर्ग समारोह func2() कॉल करने के लिए के रूप में यह बिल्कुल व्युत्पन्न वर्ग के बारे में कुछ नहीं जानता सक्षम होना चाहिए। अन्यथा कॉलिंग व्यवहार dynamic scope से संबंधित है। शायद सी ++ में, func2() बेस क्लास में static बाध्य है, लेकिन जावा में यह dynamic बांधता है?

सदस्य क्षेत्र स्थिर रूप से स्कॉप्ड है।


प्रकार का हिस्सा भाग भ्रमित कर रहा है। मैंने सोचा this में base::func1() में परिवर्तित किया गया है। सी ++ में, base::func2() पॉलिमॉर्फिज्म नहीं है, इसलिए base::func1() कहा जाता है। जावा में रहते हुए, base::func2() पॉलिमॉर्फिज्म है, इसलिए devried::func2() कहा जाता है।

कैसे func2() कक्षा बाध्यकारी अनुमान लगाया जा रहा है? या कौन सा fun2() कहा जाना चाहिए और यह कैसे निर्धारित किया जाता है।

base::func1() के पीछे क्या हुआ? क्या this (derive से base तक) के लिए कोई कलाकार यहां है? यदि नहीं, तो thisbase कक्षा में फ़ंक्शन तक पहुंचने में सक्षम है?

 void func1(){ 
      func2(); 
     } 

coderanch पर Useful discussion

+0

मुझे खेद है, लेकिन यह मेरी टिप्पणी का अंतिम हिस्सा है। मैं वास्तव में जानना चाहता हूं कि 'func2()' 'basc2()' से 'func2()' को कॉल करते समय प्रकार अनुमान कैसे लागू किया जाता है। – Kamel

+0

क्या आपका मतलब है * कैसे 'func2() 'वर्ग बाध्यकारी अनुमान लगाया जा रहा है? * – aioobe

+0

बिल्कुल। कौन सा 'fun2() 'कहा जाना चाहिए और यह कैसे निर्धारित किया जाता है। – Kamel

उत्तर

21

जावा में सभी विधियों को ओवरराइड किया जा सकता है स्वचालित रूप से virtual हैं। इसके लिए कोई ऑप्ट-इन तंत्र नहीं है (virtual कीवर्ड) क्योंकि यह सी ++ में है (और ऑप्ट-आउट करने का कोई तरीका नहीं है)।

जावा बर्ताव करता है जैसे कि आप की घोषणा की थी base::func2

रूप
virtual void func2(){ 
    printf(" I am in base:func2() \n"); 
} 

जो मामले में अपने कार्यक्रम "I am in derived:func2()" मुद्रित होता।

func2() कक्षा बाध्यकारी अनुमानित कैसे किया जा रहा है?
कौन सा fun2() कहा जाना चाहिए और यह कैसे निर्धारित किया जाता है।

गैर आभासी तरीके (virtual आपरिवर्तक के बिना सी ++ विधि) के लिए यह स्थिर प्रकार निर्धारित करता है कि जो विधि कॉल करने के लिए है। परिवर्तनीय स्थिर प्रकार परिवर्तनीय घोषणा द्वारा निर्धारित किया जाता है और यह इस बात पर निर्भर नहीं करता कि कोड कैसे निष्पादित किया जाता है।

आभासी तरीके ( virtual संशोधक और सभी जावा तरीकों के साथ सी ++ विधि) यह क्रम प्रकार निर्धारित करता है कि जो विधि कॉल करने के लिए है

। रनटाइम प्रकार रनटाइम में वास्तविक ऑब्जेक्ट का प्रकार है।

उदाहरण: आप

Fruit f = new Banana(); 

है, तो f के स्थिर प्रकार Fruit है और f के क्रम प्रकार Banana है।

यदि आप f.someNonVirtualMethod() करते हैं तो स्थिर प्रकार का उपयोग किया जाएगा और Fruit::someNonVirtualMethod कहा जाएगा। यदि आप f.someVirtualMethod() रनटाइम प्रकार का उपयोग करेंगे और Banana::someVirtualMethod कहा जाएगा।

संकलक इसे प्राप्त करने के लिए अंतर्निहित कार्यान्वयन मूल रूप से कार्यान्वयन पर निर्भर करता है, लेकिन आम तौर पर एक vtable का उपयोग किया जाता है। विवरण


नहीं हैं, तो कैसे thisbase कक्षा में कार्य करने के लिए तक पहुँचने में सक्षम है का उल्लेख करने के लिए?

void func1(){ 
    func2(); 
} 

अगर आप सोच रहे हैं क्यों func2() यहां कॉल base के func2 ऐसा इसलिए है क्योंकि

A) आप base के दायरे जिसका अर्थ है कि this के स्थिर प्रकार base है में हैं, और

बी) base में func2आभासी नहीं है, इसलिए यह स्थिर प्रकार है कि जो implementat का फैसला करता है कॉल करने के लिए आयन।

+1

(और इसके विपरीत, एक विधि 'अंतिम' बनाने से आपको "ऑप्ट आउट" करने देता है ...) –

+1

@LouisWasserman हां और नहीं। यह बेस क्लास का निर्णय है कि उप-कक्षाएं अंतिम होने पर विधि को ओवरराइड न करें। आप एक ही हस्ताक्षर के साथ एक विधि घोषित नहीं कर सकते हैं। जहां तक ​​मैं समझता हूं, यह सी ++ के लिए कुछ अलग है। – Seelenvirtuose

+1

यदि किसी विधि को ओवरराइड नहीं किया जा सकता है तो यह चर्चा करने के लिए व्यर्थ है कि यह आभासी है या नहीं। मैं कहूंगा कि निजी, अंतिम और स्थैतिक विधियां न तो वर्चुअल और न ही वर्चुअल हैं क्योंकि कोई भी नहीं जानता कि कोई तरीका किस प्रकार कॉल किया जाएगा यदि कोई इसे ओवरराइड करने में कामयाब रहे। – aioobe

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