2010-10-06 17 views
5


से गुजरती ++ मैं निम्नलिखित में उलझन में हूँ:
C++ में हम एक पैरामीटर एक समारोह के संदर्भ द्वारा पारित कर सकते हैं (एक सूचक या संदर्भ चर के रूप में यह घोषित होने के बाद) और हम अंदर इसे संशोधित करता है, तो फ़ंक्शन, फ़ंक्शन लौटने पर कॉलर पर परिवर्तन प्रतिबिंबित होते हैं।
यह जावा में नहीं हो रहा है और मुझे यकीन नहीं है कि मैं क्यों समझता हूं।जावा बनाम सी संदर्भ

उदा। इस एक वस्तु एक्स से एक विधि

public boolean aMethod(int id, myClass aClass) 
{ 
    //do some logic 
    aClass = new MyClass(); 
    //configure argument object aClass 
    return true; 
} 

में कोड बुला है:

//some code processing 
myClass obj = null; 
if(X.aMethod(2,obj)) 
{ 
    obj.methodA();//start using the object 
} 

मैं सी में इसका इस्तेमाल ++, यानी एक परिणाम सूचित करता है कि कि समारोह पैरामीटर का उपयोग किया जा सकता है वापस जाने के लिए, लेकिन जावा में यह काम नहीं करता है।
मैं if (X.aMethod (2, obj)) शाखा दर्ज करता हूं लेकिन obj शून्य है। यह शून्य क्यों है?
क्या मैंने विधि विधि के अंदर नए का उपयोग करके ढेर से स्मृति पता असाइन नहीं किया है (int id, myClass aClass)? क्या मैं समारोह में ओबीजे का "पता" पास नहीं कर रहा हूं? मैं ओबीजे को सही ढंग से निर्मित और कॉलिंग कोड में प्रयोग करने योग्य होने की उम्मीद कर रहा था। क्या मैंने जावा में स्मृति से संबंधित कुछ गलत समझा है?

+1

के संभावित डुप्लिकेट [? क्या संदर्भ द्वारा पारित के बीच अंतर है और संदर्भ से बुलाते] "जावा दर्रे तक मूल्य, Dammit है" (http://stackoverflow.com/questions/3660180/what-is-the-difference-between-pass-by-reference-and-call-by-reference) –

उत्तर

26

जावा मूल्य से सबकुछ पास करता है - संदर्भ सहित।

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

अपने aClass = लाइन से पहले:

Outside the function: 

    obj ---> <foo> 

Inside the function: 

    aClass ---> <foo> 

अपने aClass = लाइन के बाद:

Inside the function: 

    aClass ---> <bar> 

Outside the function: 

    obj ---> <foo> 

यहाँ सूचना के लिए कुंजी बात यह है कि aClassobj को इंगित नहीं करता है - यह <foo> को इंगित करता है। आप obj का पता पारित नहीं कर रहे हैं, तो आप पर obj अंक के पते को पारित कर रहे हैं। इस प्रकार, जब आप aClass अंक बदलते हैं, तो यह obj को स्पर्श नहीं करता है।


इस बारे में सोच का एक वैकल्पिक तरीका के रूप में:

जावा में,

Bar foo = new Bar(); 

सी ++ के बराबर है,

Bar *foo = new Bar(); 

इस प्रकार जब आप एक समारोह के लिए foo पारित , आप foo का पता नहीं पारित कर रहे हैं - आप वें पते को पार कर रहे हैं ई आवंटित वस्तु। जावा में &-ऑपरेटर शैली पास-बाय-रेफरेंस नहीं है जो सी/सी ++ करता है।

+0

'नया बार()', आपका मतलब है। :) –

+0

@ जोनाथन ओओएस, टाइपो।:) – Amber

1

जावा "संदर्भ द्वारा पास" नहीं कर सकता है।

जावा "मूल्य द्वारा पास करता है" का उपयोग करता है।

+0

आप उत्तर कुछ नया प्रदान नहीं करते हैं (मूल रूप से दोहराते हैं कि अन्य लोगों ने पहले ही क्या कहा है विस्तार से) और लोगों को भी भ्रमित/गुमराह करते हैं। हालांकि जेव "मूल्य से गुजरता" का उपयोग करता है लेकिन लोग अभी भी पास ऑब्जेक्ट के गुणों को बदल सकते हैं। हालांकि वे एक पूरी नई वस्तु को फिर से असाइन नहीं कर सकते (ओपी क्या करना चाहता है)। –

0

पर विचार आपके वस्तु तर्कों (जावा में) इस तरह के (सी में सचित्र ++) के रूप में पारित:

void method(TObject* arg); 
+0

'शून्य विधि (TObject * & arg);' – Ishtar

+0

@Ishtar no, 'शून्य विधि (TObject * और arg) 'सूचक के संदर्भ में होना चाहिए। तर्क को आंतरिक रूप से संशोधित किया जा सकता है (दूसरे पते पर इंगित करने के लिए), और इच्छा बाहरी रूप से प्रतिबिंबित हो - जैसे क्लाइंट का तर्क किसी अन्य पते पर इंगित कर सकता है जब 'विधि (तर्क)' रिटर्न होता है। जावा ऑब्जेक्ट को पॉइंटर्स/एड्रेस के रूप में पास करता है। जावा देव इसे 'मूल्य से' कहते हैं, लेकिन सी ++ परिप्रेक्ष्य से पॉइंटर (या पता) द्वारा पारित किया गया है, जिसमें तथ्य (और पॉइंटर्स पूरी तरह से) है। cont ... – justin

+0

@Ishtar भाग 2: सी ++ में, मूल्य == द्वारा ऑब्जेक्ट की एक प्रति पास करें। कोई प्रति नहीं है जावा के साथ। इसलिए सी ++ सिंटैक्स में जावा ऑब्जेक्ट पास करना समान है: 'शून्य विधि (टॉब्जेक्ट * तर्क); ' – justin

3

C++ यदि आप ऐसा किया क्या होगा:

void myFunct(int * pInt) { 
    pInt = // something; 
} 

// caller 
int x; 
int * myPointer = & x; 
myFunc(myPointer); 
// where does myPointer point now? 

myFunc अंदर असाइनमेंट है कॉलर के सूचक पर कोई प्रभाव नहीं। अब अगर myFunct बजाय सूचक

void myFunct(int ** ppInt) { 
    *ppInt = // something; 
} 

या सूचक के लिए एक संदर्भ सूचक ले लिया है तो आप फोन करने वाले में बदलाव देखना होगा, और कहा कि मैं क्या लगता है कि आप कर रहे हैं है।

जावा में

void myFunct (Integere anInteger) { 
     // anInteger is reference to whatever is passed 
     anInteger = new Integer(99); // no effect on caller 
} 

हम वास्तव में समारोह के लिए संदर्भ से पारित है, anInteger ऊपर फोन करने वाले के स्वामित्व में एक वस्तु के लिए एक संदर्भ है, लेकिन anInteger एक मूल्य के विधि यह करने के लिए बताए करने के लिए स्थानीय एक ही है पहले उदाहरण में पीआईएनटी को असाइन करने के रूप में, कॉलर पर कोई प्रभाव नहीं पड़ता है।

2

आपके उदाहरण में टिप्पणी से पता चलता है कि विधि aMethod ऑब्जेक्ट को कॉन्फ़िगर करने के लिए मौजूद है। । अशक्त में गुजर, कैसे पहली वस्तु instantiating और उसके बाद के बारे में में इसे पारित के बजाय वैकल्पिक रूप से, आप विधि intead वस्तु लौटने के लिए, तो तरह बना सकते हैं:

public boolean aMethod(int id) 
{ 
    myClass aClass = new MyClass(); 
    return myclass; 
} 

और:

myClass obj = X.aMethod(2); 
if(obj != null) 
{ 
    obj.methodA();//start using the object 
} 

वैकल्पिक रूप से, मैं इसे एक सम्मेलन बनाना पसंद करता हूं कि aMethod हमेशा एक मान्य वस्तु वापस करनी चाहिए। यदि यह संभव नहीं है, उदाहरण के लिए कॉन्फ़िगरेशन में गलती के कारण, विधि को इसके बजाय अपवाद फेंक दें। इस पर मेरे लेख बाहर

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