2012-06-17 20 views
37

के विज़ुअल सी ++ 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; 
}; 

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

  • आधार: गैर आभासी प्रदर्शन।
  • आधार: वर्चुअल डिस्प्ले।
  • आधार: गैर-आभासी प्रदर्शन।
  • व्युत्पन्न: वर्चुअल डिस्प्ले।

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

  • आधार:: गैर आभासी प्रदर्शन

    समस्या यह है कि जब मैं आवेदन चलाने के लिए, यह इस प्रिंट है।

  • आधार: वर्चुअल डिस्प्ले।
  • व्युत्पन्न: गैर-आभासी प्रदर्शन।
  • व्युत्पन्न: वर्चुअल डिस्प्ले।

तो या तो मैं वर्चुअल विधियों की अवधारणा को समझ नहीं पाया या दृश्य सी ++ में कुछ अजीब होता है।

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

+0

आपके पास पूरी तरह से __ बेस: गैर वर्चुअल डिस्प्ले होगा .__ आपकी लाइन को 'de.Base :: Display() 'में बदलते समय। –

उत्तर

50

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

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

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

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

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

... और अपेक्षा के अनुरूप उत्पादन पर ध्यान दें:

आधार: गैर आभासी प्रदर्शन।
आधार: वर्चुअल डिस्प्ले।
आधार: गैर-आभासी प्रदर्शन।
व्युत्पन्न: वर्चुअल डिस्प्ले।

+0

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

+0

@ लीफ लाज़र: किया गया। – sje397

+0

जैसा कि मैंने कहा था कि आप स्कोप रिज़ॉल्यूशन सिंटैक्स का उपयोग करके व्युत्पन्न उदाहरण से (गैर वर्चुअल) बेस विधि भी कॉल कर सकते हैं। –

3

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

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

virtual void fun1()=0 -> व्युत्पन्न वर्ग में अधिरोहित किया जाना चाहिए

आभासी कार्य:

virtual void fun2() ->

ओवरराइड किया जा सकता है

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

void fun3() -> यह

ओवरराइड नहीं करें आदेश में क्रम बहुरूपता आप C++

0

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

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