2011-11-26 9 views
7

यह मुझे थोड़ा आश्चर्यचकित कर रहा था, लेकिन मैं कुछ कोड के साथ खेल रहा था और पाया कि कम से कम मेरे कंप्यूटर पर, जब कोई फ़ंक्शन संदर्भ द्वारा अभिभावक वर्ग स्वीकार करता है और आप एक बच्चे के उदाहरण को पास करते हैं, तो टुकड़ा करने की समस्या नहीं होती है ' टी नहीं होता है। उदाहरण के लिए:क्या संदर्भ से गुज़रना हमेशा स्लाइसिंग मुद्दे से बचता है?

#include <iostream> 

class Parent 
{ 
public: 
    virtual void doSomething() 
    { 
     using namespace std; 
     cout << "Parent::DoSomething" << endl; 
    } 
}; 

class Child : public Parent 
{ 
public: 
    virtual void doSomething() 
    { 
     using namespace std; 
     cout << "Child::DoSomething" << endl; 
    } 
}; 

void performSomething(Parent& parent) 
{ 
    parent.doSomething(); 
} 

int main(int argc, char** argv) 
{ 
    Child myChild; 

    performSomething(myChild); 

    return 0; 
} 

यह प्रिंट Child::DoSomething प्रिंट करता है।

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

मैं बस यह सुनिश्चित करना चाहता हूं, क्या ऐसा होना चाहिए या यह उन लोगों में से एक है जो यह "मेरी मशीन पर काम करता है" उदाहरणों के प्रकार?

+0

यह "स्लाइसिंग" नहीं है। साथ ही, क्या वह कोड भी संकलित करता है? 'Std;' का उपयोग क्या है? –

+0

इसे 'नामस्थान std' का उपयोग करने का अर्थ है। मुझे लगा कि मैं इस बिंदु को प्राप्त करने में सक्षम था, लेकिन साइट पर समग्र लाभ के लिए कोड साफ़ कर दिया। – Anthony

उत्तर

9

जो व्यवहार आप देख रहे हैं वह सही है। इस तरह यह काम करना चाहिए। संदर्भ पॉइंटर्स की तरह काम करते हैं।

+0

धन्यवाद, यही मुझे लगा। जैसा कि मैंने उल्लेख किया है, मैं सिर्फ एक सैनिटी चेक चाहता था इसलिए मैंने अवैध मान्यताओं को नहीं बनाया। – Anthony

2

हां, संदर्भ के लिए बाध्यकारी गतिशील बाध्यकारी सक्षम बनाता है। यह एक वस्तु के गतिशील प्रकार और इसके स्थिर प्रकार के अंतर के कारण होता है।

यदि आप अपना पैरामीटर मान द्वारा लेते हैं, तो यह Parent वर्ग बन जाता है। यद्यपि यदि आप संदर्भ या पॉइंटर के माध्यम से कुछ पास करते हैं और वर्चुअल फ़ंक्शन को कॉल करते हैं, तो रन-टाइम संदर्भित होने वाली वास्तविक वस्तु के dynamic type या most-derived type की तलाश करेगा।

3

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

मूल्य से गुजरते समय आप समस्याओं में भाग लेते हैं कि यह फ़ंक्शन हस्ताक्षर में निर्दिष्ट प्रकार के प्रतिलिपि का उपयोग करेगा, इसलिए आप सुपरक्लास के एक बिल्कुल नए उदाहरण के साथ समाप्त हो जाते हैं।

11

"स्लाइसिंग" बेस कॉपी कन्स्ट्रक्टर की अक्षमता को व्युत्पन्न कक्षाओं से सटीक प्रकार के मिलानों को अलग करने के लिए संदर्भित करता है। स्लाइसिंग का आह्वान करने का एकमात्र तरीका बेस कॉपी कन्स्ट्रक्टर का आह्वान करना है। आमतौर पर यह तब होता है जब मूल्य से तर्क गुजर, हालांकि अन्य स्थितियों काल्पनिक जा सकता है:

class Base { }; 
class Derived : public Base { }; 

void foo(Base); 

int main() 
{ 
    Derived x; 

    Base y = x; // flagrant slicing 
    foo(x);  // slicing by passing by value 
} 

तुम कभी इस तरह के किसी भी बात कर रहे हैं, तो आप किसी भी टुकड़ा करने की क्रिया स्थितियों का सामना नहीं है।

+2

मूल्य से गुजरते समय कॉपी कन्स्ट्रक्टर का उल्लेख करें जो इस उत्तर को सही बनाता है। – dani