2013-01-09 16 views
6

संभव डुप्लिकेट:
Difference between const declarations in C++स्थिरांक कीवर्ड स्थिति

#include <iostream> 

class Bar{}; 

void foo(const Bar x){} //l5 
void foo(Bar x){}  //l6 
void foo(Bar const x){} //l7 

////pointer functions 

void foo(const Bar* x){} //l11 
void foo(Bar* x){}  //l12 
void foo(Bar* const x){} //l13 

संकलक उत्पादन: (लंबी कहानी कम l5, l6, l7 संघर्ष, लेकिन केवल l12, l13 संघर्ष)

untitled.cpp:6:6: error: redefinition of ‘void foo(Bar)’ 
untitled.cpp:5:6: error: ‘void foo(Bar)’ previously defined here 
untitled.cpp:7:6: error: redefinition of ‘void foo(Bar)’ 
untitled.cpp:5:6: error: ‘void foo(Bar)’ previously defined here 
untitled.cpp:13:6: error: redefinition of ‘void foo(Bar*)’ 
untitled.cpp:12:6: error: ‘void foo(Bar*)’ previously defined here 

क्या चल रहा है?

  1. घोषणाओं में से प्रत्येक का अर्थ क्या है
  2. क्यों वस्तु कार्यों के साथ सभी 3 घोषणाओं संघर्ष लेकिन केवल 2 सूचक कार्यों के साथ?
  3. कृपया विस्तार से बताएं कि संघर्ष l12 और l13 के बीच है, भले ही l12const कीवर्ड शामिल नहीं है
  4. सच खेद है तुच्छ सवाल

उत्तर

5

"समस्या" यह है कि पैरामीटर के मान के const नेस ओवरलोडिंग में भाग नहीं लेता है!

पहला, Bar const और const Bar पहले से ही समान अर्थ हैं, इसलिए उन्हें स्वचालित रूप से कोई समस्या होगी। लेकिन एक फ़ंक्शन पैरामीटर के रूप में const ओवरलोडिंग पर लागू नहीं होता है इसलिए फ़ंक्शन के Bar संस्करण भी वही दिखता है। पेरेमीटर में const केवल संकलक को बताता है कि आप इसे फ़ंक्शन बॉडी में संशोधित करने का इरादा नहीं रखते हैं।

उसी कारण से, Bar* और Bar* const इलाज कर रहे हैं एक ही: const पैरामीटर (क्या नहीं की ओर इशारा किया है) और, अधिक भार में भाग नहीं लेता ताकि आप एक ही समारोह में परिभाषित किया गया है का मूल्य लागू होता है। एक const वस्तु (प्रकार Bar की) करने के लिए एक गैर-स्थिरांक सूचक:

दूसरी ओर const Bar* पर कुछ पूरी तरह से अलग है। चूंकि प्रकार अलग है क्योंकि यह ओवरलोडिंग में भाग लेता है और यह फ़ंक्शन अद्वितीय होने की अनुमति देता है।

1

इससे कोई फर्क नहीं पड़ता कि आप से पहले या प्रकार नाम के बाद स्थिरांक डाल ।

15 और 17 में समान पैरामीटर तर्क सूची है।
इन 2 कार्यों को एक ही प्रोटोटाइप माना जाता है और डुप्लिकेट होते हैं।

समारोह # 1

void foo(const int x) { 
return; 
} 

समारोह # 2 - डुप्लिकेट पैरामीटर तर्क सूची

void foo(int const x) { 
return; 
} 

स्थिरांक की स्थिति 15 और उदाहरण आप में 17 के समान है।

या तो विकिपीडिया के अनुसार काम करेगा:

http://en.wikipedia.org/wiki/Const-correctness

+0

अपनी पहली वाक्य पुन: इस विशेष संदर्भ में संकलक से कोई फर्क नहीं पड़ता। आम तौर पर, हालांकि, 'कॉन्स्ट' इसके पहले क्या संशोधित करता है, और इसे संशोधित करने के बाद 'const' व्यवस्थित रूप से डालने (यानी 'int const', और' const int 'नहीं) कोड को और अधिक पठनीय बनाता है। –

0

कारण पहले तीन एक संघर्ष बनाते हैं तो वह संकलक को समझ नहीं सकता जो किसी भी मामले में उपयोग करने के लिए कार्य करते है। जब आप foo(BarObject); पर कॉल करते हैं तो संकलक उनमें से किसी भी का उपयोग कर सकता है चाहे BarObjectconst के रूप में घोषित किया गया हो या नहीं।

हालांकि संकेत के रूप में पैरामीटर, जब आप कॉल foo(BarPointer); अगर BarPointer const Bar* BarPointer; के रूप में घोषित किया गया था संकलक ]11 ले जाएगा, क्योंकि यह सुनिश्चित वस्तु जब से गुजर समारोह (नहीं मामले में संशोधित नहीं किया जा जाएगा की ओर इशारा के साथ लोगों पर

पहले तीन में मूल्य)। यदि ऐसा नहीं const है, यह पता नहीं है अगर यह ]12 या ]13 बुलाना चाहिए क्योंकि है क्या Bar* const x का मतलब है, "x क्या एक पैरामीटर के रूप पारित किया गया था की तुलना में कुछ और को इंगित नहीं कर सकते" और इस फोन करने वाले चिंता का विषय नहीं है ।घोषणाओं को

छोटे संदर्भ:

const Bar x // x is an immutable copy of the original parameter. 
Bar const x // same as above and gets compiled, but cdecl says it is a syntax error. 

const Bar* x // x points to an object that can't be changed. 
Bar* const x // x can't point to any other object than the parameter passed. 
0

मूल रूप से, क्योंकि सी ++ प्रतियां मूल्यों जब एक समारोह बुला, वहाँ पहले तीन एक कॉल करने के नजरिए से अलग करने के लिए कुछ नहीं है। (कॉलर जानता है कि फ़ंक्शन इसे अपने स्वयं के मूल्य में परिवर्तित नहीं कर सकता है, इसलिए प्रत्येक फ़ंक्शन पैरामीटर किसी भी दर पर कॉलर के परिप्रेक्ष्य से बहुत से संबंधों में निरंतर स्थिर है)।

जब आप पॉइंटर्स के बारे में बात करते हैं, तो यदि आप एक निरंतर बनाम पॉइंटर को निरंतर बनाते हैं, तो कॉलर में कोई अंतर होता है (कोई आपकी सामग्री को बदल नहीं सकता है, अन्य शक्ति)। यही कारण है कि एल 11 और एल 12 संघर्ष नहीं करते हैं।

एल 12 और एल 13 संघर्ष हालांकि वे दोनों बार * के पॉइंटर्स हैं (एक कॉन्स पॉइंटर है, एक नहीं है, एल 5-एल 7 के समान समस्या है, कॉलर में कोई फर्क नहीं पड़ता)।

यह आखिरी बिंदु हो सकता है एक छोटे से मुश्किल - ध्यान दें कि जब int const *aconst int *a रूप में ही है, इन नहींint * const a रूप में एक ही कर रहे हैं, पहले दो एक निरंतर पूर्णांक के संकेत दिए गए हैं, दूसरे के लिए एक निरंतर सूचक है एक int (यानी सूचक का मूल्य बाद में नहीं बदला जा सकता है)।

0
void foo(const Bar x){} 
void foo(Bar const x){} 

ऊपर दो, क्योंकि दोनों का कहना है कि xBar प्रकार का है समान हैं और यह const है।

void foo(Bar x){} 

ऊपर 2 के साथ यह एक संघर्ष है, क्योंकि है कि क्या xconst है या नहीं अपने कार्य का एक कार्यान्वयन विस्तार है, और समारोह हस्ताक्षर से संकलक द्वारा खारिज कर दिया गया है। तो सभी 3 फ़ंक्शन एक ही हस्ताक्षर वाले होते हैं जो void foo(Bar x) है।

void foo(Bar* x){} 
void foo(Bar* const x){} 

यह पिछले मामले के समान है; आप संकेत दे रहे हैं कि सूचक xconst है यानी आप अपने कार्य में कुछ और चीज़ों के लिए x को फिर से इंगित नहीं करेंगे। दोनों मामलों में Bar ऑब्जेक्ट x अंक गैर- const है। इस प्रकार constx की नेस फ़ंक्शन का कार्यान्वयन विवरण है।

void foo(const Bar* x){} 

यहाँ आप का संकेत कर रहे हैं कि एक Bar वस्तु जो const है x अंक। यह पिछले 2 मामलों से अलग है, और इसलिए कोई संघर्ष नहीं है।

0

पहले तीन फ़ंक्शन के लिए - constमान द्वारा स्थानांतरित चर के मामले में ओवरलोडिंग रिज़ॉल्यूशन पर कोई फर्क नहीं पड़ता है। स्टैक पर बनाए गए तर्क की प्रतिलिपि और यह समझ में नहीं आता है कि यह प्रतिलिपि बाहरी (कॉलर) दृष्टिकोण से बदल गई है या नहीं। यह स्वयं कार्य (अंदर) के लिए महत्वपूर्ण है।

दूसरे मामले के लिए, सूचक आधारित फ़ंक्शंस, यह फ़ंक्शन ओवरलोड रिज़ॉल्यूशन का महत्वपूर्ण हिस्सा है, क्योंकि स्टैक पर प्रतियां और बाहरी (कॉलर) बिंदु से प्रतियां नहीं बनाई गई हैं, इसका मतलब है कि कार्य तर्क के मूल्य को संशोधित या संशोधित नहीं करेगा। वहाँ Bar को x सूचक है, और इस Bar मूल्य मैं बदल सकते हैं x से कहा:

पिछले दो कार्यों के लिए एक संकलक करने के लिए कहते हैं का उपयोग करें। लेकिन पहले मामले में आप दूसरे मामले के विपरीत पॉइंटर x के मूल्य को बदल सकते हैं (कहें, दूसरे Bar पर इंगित करें)। और यहां हम पहली स्थिति में हैं - पॉइंटर्स की प्रतियां स्वयं ढेर पर हैं और यदि वे फ़ंक्शन के अंदर बदल गए हैं या नहीं, तो यह ओवरलोडिंग रिज़ॉल्यूशन के लिए समझ में नहीं आता है।