गैर-आभासी तरीकों को ओवरराइड करना


84

चलिए इस परिदृश्य को Visual C ++ 2010 में मानते हैं:

#include <iostream>
#include <conio.h>

using namespace std;

class Base
{
public:
    int b;
    void Display()
    {
        cout<<"Base: Non-virtual display."<<endl;
    };
    virtual void vDisplay()
    {
        cout<<"Base: Virtual display."<<endl;
    };
};

class Derived : public Base
{
public:
    int d;
    void Display()
    {
        cout<<"Derived: Non-virtual display."<<endl;
    };
    virtual void vDisplay()
    {
        cout<<"Derived: Virtual display."<<endl;
    };
};

int main()
{
    Base ba;
    Derived de;

    ba.Display();
    ba.vDisplay();
    de.Display();
    de.vDisplay();

    _getch();
    return 0;
};

सैद्धांतिक रूप से, इस छोटे अनुप्रयोग का आउटपुट होना चाहिए:

  • आधार: गैर-आभासी प्रदर्शन।
  • आधार: आभासी प्रदर्शन।
  • आधार: गैर-आभासी प्रदर्शन।
  • व्युत्पन्न: आभासी प्रदर्शन।

क्योंकि बेस क्लास का डिस्प्ले मेथड एक वर्चुअल मेथड नहीं है, इसलिए डेरेव्ड क्लास इसे ओवरराइड करने में सक्षम नहीं होना चाहिए। सही?

समस्या यह है कि जब मैं एप्लिकेशन चलाता हूं, तो यह प्रिंट करता है:

  • आधार: गैर-आभासी प्रदर्शन।
  • आधार: आभासी प्रदर्शन।
  • व्युत्पन्न: गैर-आभासी प्रदर्शन।
  • व्युत्पन्न: आभासी प्रदर्शन।

इसलिए या तो मुझे वर्चुअल तरीकों की अवधारणा समझ में नहीं आई या विजुअल C ++ में कुछ अजीब हुआ।

क्या कोई मुझे स्पष्टीकरण देने में मदद कर सकता है?


आपके पास बिल्कुल आधार होगा: गैर-आभासी प्रदर्शन। जब अपनी लाइन को बदल रहा है de.Base::Display()
v.oddou

जवाबों:


128

हां, आप थोड़ा गलत समझ रहे हैं।

व्युत्पन्न वर्ग पर समान नाम की विधि इस मामले में मूल विधि को छिपाएगी। आप सोचेंगे कि यदि ऐसा नहीं होता, तो बेस क्लास नॉन-वर्चुअल विधि के समान नाम वाली एक विधि बनाने की कोशिश में त्रुटि आनी चाहिए। इसकी अनुमति है और यह कोई समस्या नहीं है - और यदि आप विधि को सीधे कहते हैं जैसा आपने किया है तो इसे ठीक कहा जाएगा।

लेकिन, गैर-आभासी होने के नाते, C ++ विधि लुकअप तंत्र जो कि बहुरूपता के लिए अनुमति देता है, का उपयोग नहीं किया जाएगा। उदाहरण के लिए यदि आपने अपने व्युत्पन्न वर्ग का एक उदाहरण बनाया है, लेकिन बेस क्लास के लिए एक पॉइंटर के माध्यम से अपनी 'डिस्प्ले' विधि कहा जाता है, तो आधार की विधि को बुलाया जाएगा, जबकि 'vDisplay' के लिए व्युत्पन्न विधि कहा जाएगा।

उदाहरण के लिए, इन पंक्तियों को जोड़ने का प्रयास करें:

Base *b = &ba;
b->Display();
b->vDisplay();
b = &de;
b->Display();
b->vDisplay();

... और उम्मीद के मुताबिक आउटपुट देखें:

आधार: गैर-आभासी प्रदर्शन।
आधार: आभासी प्रदर्शन।
आधार: गैर-आभासी प्रदर्शन।
व्युत्पन्न: आभासी प्रदर्शन।


हाय @ sje397, आपके उत्तर के लिए धन्यवाद। क्या आप विधि को कॉल करने का एक उदाहरण लिख सकते हैं, जैसा कि आपने कहा, बेस क्लास के लिए एक सूचक के माध्यम से? धन्यवाद!
लीफ लजार

जैसा कि मैंने कहा था कि आप एएलएसओ (गैर-आभासी) बेस पद्धति को व्युत्पन्न उदाहरण से कॉल कर सकते हैं, गुंजाइश रिज़ॉल्यूशन सिंटैक्स का उपयोग कर सकते हैं।
v.oddou

1
इसलिए, बस यह सुनिश्चित करने के लिए, मैं बेस क्लास में एक विधि को परिभाषित कर सकता हूं, और इसे व्युत्पन्न वर्ग में ओवरराइड कर सकता हूं, भले ही इसे आभासी घोषित किया जाए या नहीं। अंतर केवल इतना है कि यदि एक आधार सूचक एक व्युत्पन्न वर्ग वस्तु की ओर इशारा करता है, तो उस पद्धति को कॉल करने से आधार वर्ग की विधि शांत हो जाएगी यदि यह आभासी नहीं है, और व्युत्पन्न वर्ग की विधि आभासी है। क्या वह सही है? क्या कोई और अंतर है?
21

@Cupidvogel हां, यह सही है। इसे 'वर्चुअल' घोषित करने का मतलब है कि C ++ पॉलीमॉर्फिज़्म का समर्थन करने के लिए तंत्र का उपयोग करेगा और यह देखने के लिए जांच करेगा कि क्या बेस क्लास पॉइंटर के माध्यम से कॉल करने पर विधि का अधिक व्युत्पन्न संस्करण है। मैं किसी अन्य अंतर के बारे में नहीं सोच सकता।
sje397

क्या केवल हेडर फ़ाइल को बदलना पर्याप्त है? या, स्रोत को "वर्चुअल" कीवर्ड के साथ संकलित किया जाना चाहिए?
पॉल नोपफ

14

हाँ, आपको कुछ गलत समझा है:

शुद्ध आभासी कार्य:

virtual void fun1()=0 -> व्युत्पन्न वर्ग में ओवरराइड होना चाहिए

आभासी कार्य:

virtual void fun2() -> ओवरराइड किया जा सकता है

सामान्य कार्य:

void fun3() -> इसे ओवरराइड न करें

क्रम बहुरूपता को प्राप्त करने के लिए आपको c ++ में वर्चुअल फ़ंक्शंस को ओवरराइड करना होगा


5

मुझे लगता है कि इसे स्थिर बनाम गतिशील बंधन के संदर्भ में देखना बेहतर होगा।

यदि विधि गैर-आभासी है (यह जावा के विपरीत सी ++ में पहले से ही डिफ़ॉल्ट है), तो विधि संकलन समय पर कॉलर को बांधती है जो वास्तविक वस्तु को जानना असंभव है जिसे रनटाइम पर इंगित किया जाएगा। तो, चर प्रकार वह सब है जो मायने रखता है जो 'आधार' है।

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