2013-04-02 1 views
5

एक कोड में मैं निम्नलिखित निर्माण देखें। तो, मुझे आश्चर्य है कि क्यों निम्नलिखित निर्माण का उपयोग नहीं:जब "class_name obj_name = func()" को "class_name obj_name {func()}" से प्रतिस्थापित करने के लिए समझ में आता है?</p> <pre><code>const class_name obj_name{func()}; </code></pre> <p>समारोह() वर्ग <code>class_name</code> कहा जाता है की एक ऑब्जेक्ट:

const class_name obj_name = func(); 

उत्तर

5
const class_name obj_name{func()}; 

ऊपर लिखकर, लेखक वर्दी प्रारंभ वाक्य रचना (द्वारा सी ++ 11 शुरू की) का पालन करने, इतनी के रूप में अप्रिय पार्स की वजह से समस्याओं से बचने की कोशिश कर रहा है और सबसे अधिक परेशानी पार्स, जिसमें अनुभवी प्रोग्रामर भी गलती से फंस जाते हैं। वह अपने दिमाग में सबसे अच्छा अभ्यास करने की कोशिश कर रहा है ताकि वह कभी-कभी बताए गए पार्सिंग मुद्दों में फंस नहीं पाए।

इस पर विचार करें,

struct X { /*....*/ }; // some class 

struct Y 
{ 
    Y(); 
    Y(int i); 
    Y(X x); 
}; 

अब एक यह लिख सकते हैं:

Y y(100); // declare an object y of type Y 

कि दूसरे निर्माता है, जो ठीक है invokes। अभी तक, बहुत अच्छा!

लेकिन गलती से एक भी इस बारे में:

Y y(); 

(गलती से) यह सोच कर कि यह डिफ़ॉल्ट निर्माता invokes। लेकिन तथ्य यह है कि यह डिफ़ॉल्ट कन्स्ट्रक्टर का आह्वान नहीं करता है। इसके बजाय यह एक समारोह y घोषित करता है जो कोई तर्क नहीं लेता है, और Y देता है। इसे C12+ में vexing parse कहा जाता है।

इसी तरह, एक इस

Y y(X()); 

यह सोच कर कि यह तीसरी निर्माता प्रकार X जो मक्खी पर बनाई गई है की एक वस्तु गुजर invokes लिख सकते हैं (गलती से),। फिर, यह गलत है।इसके बजाय यह एक फ़ंक्शन y घोषित करता है जो एक फ़ंक्शन पॉइंटर लेता है (प्रकार का फ़ंक्शन जो कुछ भी नहीं लेता है और X लौटाता है) और Y लौटाता है। इसे सी ++ में सबसे अधिक परेशानी पार्स कहा जाता है।

तो वर्दी प्रारंभ वाक्य रचना ऐसे सभी मुद्दों से बचा जाता है, तो आप यह लिख सकते हैं:

Y y1{};  // invokes 1st constructor 
Y y2{100}; // invokes 2nd constructor 
Y y3{X{}}; // invokes 3rd constructor 

और एक ही वाक्य रचना के बाद,

Y { function_call() }; 

const class_name obj_name { func() }; // taken from your question! 

वर्दी और निश्चित रूप से सबसे अच्छा अभ्यास, 'isn है टी?

उम्मीद है कि मदद करता है।

1

सी ++ 11 के रूप में uniform initialization सुविधा शुरू की गई थी जो प्रकार प्रारंभ करने के कई तरीके प्रदान करता है।

इस मामले में, दोनों वाक्यविन्यास class_name(class_name const&) कॉपी कन्स्ट्रक्टर (यदि कोई मौजूद है) को कॉल करेंगे। इसलिए कोई वास्तविक अंतर नहीं है। यह सिर्फ वरीयता का मामला है।

यह ध्यान रखें कि {} वाक्य रचना हमेशा इस मामले में की तरह व्यवहार नहीं करते है: अगर कोई उचित प्रकार का एक initialization_list निर्माता है, कि निर्माता प्रयोग किया जाता है, अन्यथा वर्ग तत्वों उचित निर्माता का उपयोग कर प्रारंभ कर रहे हैं ।

मामलों में जहां सबसे अप्रिय पार्स सिद्धांत (अगर यह संभवतः एक समारोह प्रोटोटाइप के रूप में व्याख्या की जा सकती है, तो यह हो जाएगा) आप संकलक कि पीछा कर रहा है बताने के लिए दो में से किसी एक का उपयोग करने के लिए आवश्यक हैं स्ट्राइक नहीं एक समारोह प्रोटोटाइप:

typename class_name obj_name(func()); 
class_name obj_name { func() }; 
संबंधित मुद्दे