2010-12-24 11 views
5

निम्नलिखित कोड खंड पर विचार करें:व्यवहार वस्तु ++ संदर्भ

class Window // Base class for C++ virtual function example 
    { 
     public: 
      virtual void Create() // virtual function for C++ virtual function example 
      { 
       cout <<"Base class Window"<<endl; 
      } 
    }; 

    class CommandButton : public Window 
    { 
     public: 
      void Create() 
      { 
       cout<<"Derived class Command Button - Overridden C++ virtual function"<<endl; 
      } 
    }; 

    int main() 
    { 
     Window *button = new CommandButton; 
     Window& aRef = *button; 
     aRef.Create(); // Output: Derived class Command Button - Overridden C++ virtual function 
     Window bRef=*button; 
     bRef.Create(); // Output: Base class Window 

     return 0; 
    } 

दोनों आरिफ और BREF असाइन किए जाएंगे * बटन, लेकिन क्यों दो उत्पादन अलग हैं। संदर्भ प्रकार और गैर संदर्भ प्रकार को निर्दिष्ट करने के बीच क्या अंतर है?

उत्तर

10

आपको स्लाइसिंग समस्या का सामना करना पड़ा है।

Window bRef =*button; 

यहां बीआरएफ संदर्भ नहीं बल्कि एक वस्तु है। जब आप बीआरएफ पर व्युत्पन्न प्रकार असाइन करते हैं तो आप व्युत्पन्न भाग को टुकड़े कर रहे हैं जिससे आपको केवल एक विंडो ऑब्जेक्ट बनाया गया है जिसे कमांडबटन बनाया गया है।

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

एक तरफ ध्यान दें: वर्चुअल सदस्यों वाले वर्ग में वर्चुअल विनाशक भी होना चाहिए।

+0

का जवाब दे रहा था, इसलिए, इस प्रतिलिपि के साथ निर्माता देर से बाध्यकारी बस नहीं होता है, है ना? –

+0

गनर: देर बाध्यकारी यहां प्रासंगिक नहीं है। आप एक नई स्थिर रूप से टाइप की गई वस्तु बना रहे हैं जो गतिशील रूप से टाइप की गई वस्तु नहीं है (इसके लिए आपको संदर्भ या सूचक की आवश्यकता है)। –

+0

आभासी या संरक्षित विनाशक। कई डिज़ाइनों में सदस्य कार्यों को बहुरूप रूप से हटाए बिना बहुलक रूप से कहा जाता है। –

2
Window bRef=*button; 
bRef.Create(); // Output: Base class Window 

bRef के स्थिर करने के साथ ही गतिशील प्रकार Window ही है। वर्चुअल तंत्र केवल संदर्भ और पॉइंटर्स के साथ काम करता है। bRef एक ऑब्जेक्ट एक संदर्भ या सूचक नहीं है।

1
Window bRef=*button; 
bRef.Create(); // Output: Base class Window 

यहाँ bRefbutton के संदर्भ (आप बस यह नाम इसलिए दिया) नहीं है। बीआरएफ को केवल बेस सबोबजेक्ट मिलता है जो Window है।

+0

लेकिन इस असाइनमेंट का प्रभाव मैं क्या कर रहा हूं। चूंकि * बटन कमांडबटन का उपयोग करके प्रारंभ किया गया था, तो क्या यह तब संकलित त्रुटि नहीं होनी चाहिए? –

+0

नहीं। आपकी विंडो क्लास में कॉपी कॉपी कन्स्ट्रक्टर विंडो (कॉन्स विंडो और) है। चूंकि कमांडबटन एक खिड़की है, यह उस प्रतिलिपि निर्माता के लिए तर्क हो सकता है। – cgmb

+0

@ Slavik81: हाँ, तो? मैंने जो कहा वह अवैध कैसे करता है? – Nawaz

7
  • aRefWindowस्थिर प्रकार लेकिन CommandButtonगतिशील प्रकार है
  • bRef बस प्रकार Window का एक उद्देश्य
( CommandButton'भाग' प्रतिलिपि में खो गया था) है

इसे आमतौर पर object slicing के रूप में जाना जाता है डी आमतौर पर आधार वर्गों को या तो सार (शुद्ध वर्चुअल फ़ंक्शन प्रदान करके) या गैर प्रतिलिपि बनाने के लिए रोक दिया जाता है (उदाहरण के लिए boost::noncopyable का उपयोग करके), क्योंकि समाधान समाधान कोड को Window& aRef = *button; पर संकलित करने में विफल हो जाएगा।


अब, क्यों bRef.Create() कॉल Window::Create करता है? खैर, bRef में Window से अधिक कुछ भी नहीं है, इसलिए वास्तव में कोई विकल्प नहीं है। यह अनिवार्य रूप से Window घोषित करना और Create पर कॉल करना है: तथ्य यह है कि bRef को CommandButton से कॉपी किया गया था उदाहरण अप्रासंगिक है क्योंकि प्रतिलिपि में CommandButton भाग खो गया था।

मैं मानक को उद्धृत करके यह स्पष्ट करने की कोशिश करूंगा (10।3/6):

[ध्यान दें: एक आभासी समारोह के कॉल की व्याख्या, वस्तु है जिसके लिए वह कहा जाता है (गतिशील प्रकार) की प्रकार पर निर्भर करता है, जबकि व्याख्या गैर-वर्चुअल सदस्य फ़ंक्शन का कॉल केवल पॉइंटर या संदर्भ पर निर्भर करता है जो उस ऑब्जेक्ट को इंगित करता है ( स्थिर प्रकार) (5.2.2)। ]

केवल एक सूचक या संदर्भ संकेत के माध्यम से एक वस्तु का स्थिर प्रकार इसके गतिशील प्रकार से अलग हो सकता है।

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