2011-08-22 16 views
46

सी ++ में, आप कन्स्ट्रक्टर चलने से पहले कक्षा के फ़ील्ड को आरंभ करने के लिए प्रारंभकर्ता सूची का उपयोग कर सकते हैं। उदाहरण के लिए:जावा में प्रारंभिक सूचियां क्यों नहीं हैं जैसे सी ++ में?

Foo::Foo(string s, double d, int n) : name(s), weight(d), age(n) { 
    // Empty; already handled! 
} 

मुझे उत्सुकता है कि जावा में एक समान सुविधा क्यों नहीं है। खंड 1: कोर जावा के अनुसार

सी ++ क्षेत्र कंस्ट्रक्टर्स कॉल करने के लिए इस विशेष सिंटैक्स का उपयोग करता। जावा में, इसकी कोई आवश्यकता नहीं है क्योंकि ऑब्जेक्ट्स में कोई उप-तत्व नहीं है, केवल अन्य ऑब्जेक्ट्स के पॉइंटर्स हैं।

यहाँ मेरी सवाल कर रहे हैं: "क्योंकि वस्तुओं कोई subobjects है"

  1. क्या वे से क्या मतलब है मुझे समझ में नहीं आता कि सबबोजेक्ट क्या है (मैंने इसे देखने की कोशिश की); क्या उनका मतलब उप-वर्ग का एक झुकाव है जो सुपरक्लास को बढ़ाता है?

  2. के लिए क्यों जावा सी ++ की तरह प्रारंभकर्ता सूचियों नहीं है के रूप में, मुझे लगता है होता है कि कारण है क्योंकि सभी क्षेत्रों में पहले से ही जावा में डिफ़ॉल्ट रूप से प्रारंभ कर रहे हैं और इसलिए भी क्योंकि जावा super कीवर्ड (या आधार में सुपर कॉल करने के लिए उपयोग करता है सी ++ लिंगो) -क्लास निर्माता। क्या ये सही है?

उत्तर

86

सी ++ में, प्रारंभकर्ता सूचियों क्योंकि है कि जावा में या तो मौजूद नहीं हैं कुछ भाषा सुविधाओं के लिए आवश्यक हैं या जावा में अलग तरह से काम करते हैं:

  1. const: सी ++ में, आप एक फ़ील्ड const चिह्नित कर रहे हैं कि करने के लिए आवंटित नहीं किया जा सकता को परिभाषित करने और चाहिए कर सकते हैं प्रारंभकर्ता सूची में शुरू किया जाना चाहिए। जावा में final फ़ील्ड हैं, लेकिन आप एक निर्माता के शरीर में final फ़ील्ड असाइन कर सकते हैं।सी ++ में, कन्स्ट्रक्टर में const फ़ील्ड को असाइन करना अवैध है।

  2. संदर्भ: सी ++ में, संदर्भ (पॉइंटर्स के विपरीत) कुछ ऑब्जेक्ट से जुड़ने के लिए प्रारंभ किया जाना चाहिए। प्रारंभकर्ता के बिना संदर्भ बनाना अवैध है। सी ++ में, जिस तरीके से आप इसे निर्दिष्ट करते हैं वह प्रारंभकर्ता सूची के साथ होता है, क्योंकि यदि आप इसे पहले शुरू किए बिना कन्स्ट्रक्टर के शरीर में संदर्भ का संदर्भ लेते हैं तो आप एक प्रारंभिक संदर्भ का उपयोग करेंगे। जावा में, ऑब्जेक्ट संदर्भ C++ पॉइंटर्स की तरह व्यवहार करते हैं और बनाए जाने के बाद असाइन किए जा सकते हैं। वे अन्यथा null पर डिफ़ॉल्ट रूप से डिफ़ॉल्ट हैं।

  3. डायरेक्ट सबोबजेक्ट। सी ++ में, किसी ऑब्जेक्ट में ऑब्जेक्ट सीधे फ़ील्ड के रूप में हो सकता है, जबकि जावा ऑब्जेक्ट्स में केवल संदर्भ उन ऑब्जेक्ट्स को हो सकता है। यही है, सी ++ में, यदि आप किसी ऑब्जेक्ट की घोषणा करते हैं जिसमें सदस्य के रूप में string है, तो उस स्ट्रिंग के लिए संग्रहण स्थान सीधे ऑब्जेक्ट के लिए स्थान पर बनाया गया है, जबकि जावा में आपको बस किसी अन्य String के संदर्भ के लिए स्थान मिलता है ऑब्जेक्ट कहीं और संग्रहीत। नतीजतन, सी ++ को उन सबोबजेक्ट्स प्रारंभिक मान देने के लिए एक तरीका प्रदान करने की आवश्यकता है, अन्यथा वे केवल अनियंत्रित रहेंगे। डिफ़ॉल्ट रूप से यह उन प्रकार के लिए डिफ़ॉल्ट कन्स्ट्रक्टर का उपयोग करता है, लेकिन यदि आप एक अलग कन्स्ट्रक्टर का उपयोग करना चाहते हैं या कोई डिफ़ॉल्ट कन्स्ट्रक्टर उपलब्ध नहीं है तो प्रारंभकर्ता सूची आपको इसे बाईपास करने का एक तरीका प्रदान करती है। जावा में, आपको इसके बारे में चिंता करने की आवश्यकता नहीं है क्योंकि संदर्भ null पर डिफ़ॉल्ट होंगे, और फिर आप उन ऑब्जेक्ट्स को संदर्भित करने के लिए असाइन कर सकते हैं जिन्हें आप वास्तव में संदर्भित करना चाहते हैं। यदि आप एक गैर-डिफ़ॉल्ट कन्स्ट्रक्टर का उपयोग करना चाहते हैं, तो इसके लिए आपको किसी भी विशेष वाक्यविन्यास की आवश्यकता नहीं है; उचित कन्स्ट्रक्टर के माध्यम से शुरू की गई एक नई वस्तु के संदर्भ को बस सेट करें।

कुछ मामलों में जहां जावा प्रारंभकर्ता सूची (उदाहरण के लिए, सुपर क्लास कंस्ट्रक्टर कॉल करने के लिए या अपने क्षेत्रों के लिए मूलभूत मूल्यों दे) चाहते हो सकता है में, यह दो अन्य भाषा सुविधाओं के माध्यम से नियंत्रित किया जाता है: super कीवर्ड सुपर क्लास कंस्ट्रक्टर आह्वान करने के लिए , और तथ्य यह है कि जावा ऑब्जेक्ट्स अपने फ़ील्ड को डिफ़ॉल्ट मान उस बिंदु पर दे सकते हैं जिस पर उन्हें घोषित किया जाता है। चूंकि सी ++ में एकाधिक विरासत है, इसलिए केवल एक super कीवर्ड अनजाने में एक एकल बेस क्लास को संदर्भित नहीं करेगा, और सी ++ 11 सी ++ से पहले कक्षा में डिफ़ॉल्ट प्रारंभकर्ताओं का समर्थन नहीं करता था और प्रारंभकर्ता सूचियों पर भरोसा करना था।

आशा है कि इससे मदद मिलती है!

+0

उत्कृष्ट जवाब। मुझे अपने प्रश्न के प्रतिक्रिया समय पर बहुत आश्चर्य हुआ। पंजीकरण के बाद मैं आपको उखाड़ दूंगा। इसके अलावा, सी ++ 0x में परिवर्तन के बारे में एक लिंक की सराहना की जाएगी। –

+0

@ जेसी- मदद करने में खुशी हुई! अगर आपको लगता है कि यह सवाल का जवाब देता है तो भी जवाब स्वीकार करना न भूलें। :-) और मैंने प्रश्न में सी ++ 0x परिवर्तन के लिए एक लिंक शामिल किया है। – templatetypedef

+1

रात में एक घंटे से अधिक समय में 1 9 वोट ... अच्छा :-) –

1

क्योंकि जावा को उन फ़ील्ड के प्रारंभिकरण की अनुमति देने की आवश्यकता नहीं है जिनके प्रकार शून्य-मूल्य नहीं है।

C++ में

class C { 
    D d; 
} 
d के लिए एक सदस्य प्रारंभकर्ता बिना

, D::D() जो यह क्षेत्र को प्रारंभ करने के लिए असंभव अगर वहाँ D के लिए कोई शून्य प्रकार है बनाता है बुलाया जाएगा। ऐसा तब हो सकता है जब D::D() स्पष्ट रूप से private घोषित किया गया हो।

जावा में, सभी संदर्भ प्रकारों, null के लिए zero-value ज्ञात है, इसलिए एक फ़ील्ड हमेशा प्रारंभ किया जा सकता है।

जावा भी बनाने के लिए काम का एक समूह करता है सुनिश्चित करें * कि सभी final क्षेत्रों, पहली बार उपयोग करने से पहले और इससे पहले कि निर्माता समाप्त होता है प्रारंभ कर रहे हैं ताकि जबकि जावा सी ++ के const क्षेत्र प्रारंभ आवश्यकता की तरह एक आवश्यकता है, यह सिर्फ this.fieldName = <expression> निर्माता में overloads शरीर प्रारंभिक क्षेत्र का मतलब है।

  • : सापेक्ष ctor में फेंक दिया अपवाद भी ओवरराइड विधि, आदि आधार वर्ग से कॉल
+0

उत्तर के लिए धन्यवाद का उपयोग कर सकते हैं। हालांकि, मैं "शून्य मान" शब्द से थोड़ा थके हुए था, क्योंकि ऐसा लगता है कि यह पूर्णांक 0 के बारे में बात कर रहा है, जबकि सी ++ ऑक्स (नलप्टर) और जावा नल में मैं समकक्ष मानता हूं। –

+0

@ जेसे, मैंने "शून्य-मूल्य" शब्द का आविष्कार नहीं किया। प्रोग्रामिंग भाषा विनिर्देश दस्तावेजों और इसी तरह प्रोग्रामिंग में यह एक आम शब्द है। जैसे ["प्रभावी गो"] (http://golang.org/doc/effective_go.html) रिटर्न पैरामीटर के बारे में कहते हैं, "जब नाम दिया जाता है, तो फ़ंक्शन शुरू होने पर उन्हें उनके प्रकार के शून्य मानों में प्रारंभ किया जाता है" और [भाषा स्पेक ] (http://golang.org/doc/go_spec.html#The_zero_value) सूचक प्रकार के लिए शून्य मान के रूप में 'शून्य 'को परिभाषित करता है। –

+0

"शून्य-मान" के संबंध में लिंक के लिए धन्यवाद। जैसा कि आप जानते हैं, अलग-अलग भाषाएं समान अवधारणाओं के बारे में विभिन्न शब्दावली का उपयोग करती हैं, जैसे [यहां] (http://stackoverflow.com/questions/1350819/c-free-store-vs-heap)। तो, मैं दोनों को अलग करने की सिफारिश करता हूं। –

8

सी ++

वहाँ

ClassType t(initialization arguments); 

और

ClassType * pt; 

के बीच एक अंतर उत्तरार्द्ध प्रारंभ करने की आवश्यकता नहीं है (शून्य पर सेट) है। पूर्व करता है इसे एक पूर्णांक के रूप में सोचें। आपके पास मूल्य के बिना int नहीं हो सकता है, लेकिन आपके पास मूल्य के बिना एक इंट पॉइंटर हो सकता है।

तो आपके पास:

class ClassType 
{ 
    OtherClass value; 
    OtherClass * reference; 
}; 

फिर घोषणा:

ClassType object; 

स्वचालित रूप से value में OtherClass का एक उदाहरण बनाता है।इसलिए, यदि OtherClass प्रारंभिक है, तो इसे ClassType कन्स्ट्रक्टर में किया जाना चाहिए। हालांकि, reference सिर्फ एक सूचक (स्मृति में पता) है और यह अनियंत्रित रह सकता है। आप OtherClass का एक उदाहरण चाहते हैं तो आप का उपयोग करना चाहिए

object.reference = new OtherClass(initialization arguments); 

जावा

वहाँ केवल

class ClassType 
{ 
    OtherClass reference; 
} 

यह सी में एक सूचक ++ के बराबर है है। इस मामले करते हुए करते हैं:

ClassType object = new ClassType(); 

आप स्वचालित रूप से OtherClass का एक उदाहरण नहीं बनाते हैं। इसलिए, जब तक आप चाहें तो आपको कन्स्ट्रक्टर में कुछ भी प्रारंभ करने की आवश्यकता नहीं है। जब आप OtherClass का ऑब्जेक्ट चाहते हैं तो आप

object.reference = new OtherClass(); 
+0

उत्तर को समझने में बहुत आसान है। –