2008-11-06 14 views
8

मैं ऐसा करते हैं तो:सी ++ स्थिरांक सवाल

// In header 
class Foo { 
void foo(bar*); 
}; 

// In cpp 
void Foo::foo(bar* const pBar) { 
//Stuff 
} 

संकलक शिकायत नहीं है कि फू :: foo के लिए हस्ताक्षर मेल नहीं खाते। हालांकि अगर मेरे पास:

void foo(const bar*); //In header 
void Foo::foo(bar*) {} //In cpp 

कोड संकलित करने में विफल रहेगा।

क्या चल रहा है? मैं जीसीसी 4.1.x

+0

आप अपने दूसरे उदाहरण में * के दूसरे पक्ष पर स्थिरांक डाल करने के लिए मतलब है? कुछ लोग इसके अर्थ में अंतर बताकर जवाब दे रहे हैं, और अन्य लोग इस बात को समझकर जवाब दे रहे हैं कि कॉन्स सीपीपी या एच फाइल में है या नहीं। –

+0

आपको अपने प्रश्न के लिए एक एवर चुनना चाहिए या अपडेट करना चाहिए यदि यह वह उत्तर नहीं है जिसे आप ढूंढ रहे हैं। –

उत्तर

1

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

// In header 
class Foo { 
void foo(int b); 
}; 

// In cpp 
void Foo::foo(const int b) { 
//Stuff 
} 

तुम भी ऐसा कर सकते हैं:

// In header 
class Foo { 
void foo(const int b); 
}; 

// In cpp 
void Foo::foo(int b) { 
//Stuff 
} 

पूर्णांक के बाद से मूल्य से पारित कर दिया है, constness फर्क नहीं पड़ता।

दूसरे उदाहरण में आप कह रहे हैं अपने कार्य एक प्रकार के लिए सूचक ले जाता है कि है, लेकिन फिर एक और प्रकार के लिए सूचक ले रही है के रूप में इसे लागू, इसलिए यह विफल रहता है।

15

पहले में, आपने संकलक का वादा किया है, लेकिन कक्षा के अन्य उपयोगकर्ताओं को नहीं कि आप चर संपादित नहीं करेंगे।

अपने दूसरे उदाहरण में, आप वर्ग है कि आप अपने चर को संपादित नहीं होगा के अन्य उपयोगकर्ताओं का वादा किया है, लेकिन उस वादे को बनाए रखने में नाकाम रहे।

मैं भी ध्यान देना चाहिए वहाँ

bar* const variable 

और

बीच एक स्पष्ट अंतर
const bar* variable 

और

const bar* const variable 

प्रथम रूप में, सूचक कभी नहीं बदल जाएगा है, लेकिन आप जिस वस्तु को इंगित करते हैं उसे संपादित कर सकते हैं। दूसरे रूप में, आप पॉइंटर को संपादित कर सकते हैं (इसे किसी अन्य ऑब्जेक्ट पर इंगित करें), लेकिन यह वैरिएबल कभी भी इंगित नहीं करता है। अंतिम रूप में, आप न तो सूचक को संपादित करेंगे, न ही ऑब्जेक्ट को इंगित करेंगे। Reference

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

Foo::func1(const int x) {} 
Foo::func2(const int* const x) {} 

:

Foo::func1(const int x) {} 
Foo::func2(const int *x) {} 

या:

class Foo { 
    void func1 (int x); 
    void func2 (int *x); 
} 

आप निम्न कार्यान्वयन संकलन कर सकते हैं: एक वर्ग को देखते हुए। आपने अपने उपयोगकर्ताओं को बताया है कि आप संभवतः अपने चर संपादित कर सकते हैं। आपके कार्यान्वयन में, आपने संकलक को बताया है कि यह विशेष कार्यान्वयन उन चरों को संपादित नहीं करेगा, भले ही आपके द्वारा बताए गए उपयोगकर्ताओं को बताया गया हो। आपने उपयोगकर्ता को कोई वादा नहीं तोड़ा है, और इसलिए कोड संकलित करता है।

+0

मुझे नहीं लगता कि अपने सिद्धांत का मानना ​​है: 1) यदि आप यह घोषणा "int *" और लागू "स्थिरांक पूर्णांक *" है, तो अपने उदाहरण के रूप में, यह संकलन नहीं है। 2) यदि आप मूल्य से गुजरते हैं, तो आप कॉन्स घोषित कर सकते हैं और कॉन्स्ट के साथ लागू नहीं कर सकते हैं। जब आप मूल्य से गुजरते हैं तो इसका अर्थ नहीं होता है। –

+0

हां। मैं मानता हूँ कि आप गलत हैं। शून्य एफ (int const *); शून्य एफ (int *) से अलग है; मुझे लगता है कि आप शून्य एफ (int * const) लिखना चाहते थे; शून्य एफ (int *) के समान हस्ताक्षर है; आपको अपना उदाहरण बदलना चाहिए क्योंकि इससे शुरुआती भ्रम हो सकता है। –

0

पूर्व में, const इंटरफेस, केवल कार्यान्वयन को प्रभावित नहीं करता। आप कंपाइलर से कह रहे हैं, "मैं इस फ़ंक्शन के भीतर bar* के मान को बदलने वाला नहीं हूं"। आप अभी भी पॉइंटर द्वारा इंगित किए गए परिवर्तन को बदल सकते हैं। बाद में, आप संकलक (और सभी कॉलर्स) आप करने के लिए bar संरचना कि bar*अंक में परिवर्तन नहीं होगा कह रहे हैं।

+0

मुझे लगता है कि आप अंतिम वाक्य में मतलब है "आप बार में बदलाव नहीं करेगी कि बार * अंक करने के लिए"। "बार * बिंदुओं को बदलें" का अर्थ बदलें "बार * एक नया मान दें", जो कि दूसरे उदाहरण में बिल्कुल ठीक है। –

+0

इसके लिए धन्यवाद, तय। Pronouns स्पष्टता का झुकाव हैं। –

6

this question, this question, और this question देखें।

असल में, केवल तभी का मतलब है कि फ़ंक्शन पॉइंटर के मान को संशोधित नहीं करेगा। पॉइंटर्स सामग्री हेडर के हस्ताक्षर के समान नहीं है।

0

तो में दूसरा स्थिरांक:

void Foo::foo(const bar* const); 

विधि हस्ताक्षर के हिस्सा नहीं है?

+1

आप .h फ़ाइल में कोई विधि घोषित करते हैं, तो आप इसे .cpp में परिभाषित करते हैं।घोषणा में सब कुछ हस्ताक्षर (दोनों consts) का हिस्सा है, ऐसा प्रतीत होता है कि परिभाषा में आप तर्क प्रकार को अधिक बारीकी से परिशोधित कर सकते हैं जब तक कि परिभाषा घोषणा के अर्थशास्त्र को तोड़ती नहीं है। –

+0

@ मामिन: सही। उदाहरण के लिए, यदि आप घोषित करते हैं तो लिंकर त्रुटि को देखें (लेकिन परिभाषित न करें) "void foo (const int * const a)", और फिर उसे कॉल करें। जीसीसी द्वारा लापता हस्ताक्षर की रिपोर्ट "foo (int const *)" है। –

+0

सरल: यदि आप कॉन्स्ट को जोड़ते/हटाते हैं तो यह हस्ताक्षर का हिस्सा नहीं होगा। तो शून्य फू (int * const); और शून्य फू (int *); वास्तव में एक ही हस्ताक्षर है। लेकिन शून्य फू (int const *); और शून्य फू (int *); अलग-अलग हस्ताक्षर हैं: पैरामीटर प्रकार में कोई भी कॉन्स नहीं जोड़ा गया है, लेकिन उस प्रकार के लिए इंगित किया गया है। –

0

यह समझने के लिए सरल एक चर एक सूचक के अलावा अन्य प्रकार के साथ है। उदाहरण के लिए, आप निम्नलिखित समारोह घोषणा हो सकती है:

void foo(int i); 

परिभाषा इस तरह दिख सकता:

void foo(const int i) { ... } 

चाहे चर 'i' स्थिरांक या परिभाषा साथ नहीं है एक कार्यान्वयन विस्तार है । इसका उस कार्य के ग्राहकों के लिए कोई प्रभाव नहीं पड़ता है।

+0

मुझे नहीं पता कि SO उपयोगकर्ता कैसे वोट करते हैं। उपरोक्त +15 के साथ शीर्ष वोट एक उत्तर है जिसमें अंत में गलत बयान है और इसे ठीक करने की तरह महसूस नहीं होता है (पीपीएल ने उसे 3 महीने पहले बताया था), और -1 पर यह जवाब ठीक था और बहुत बेहतर समझाया गया (IMHO)। निष्पक्षता के लिए +1 कर रहे हैं। –

+0

सहमत हुए। मुझे समझ में नहीं आता कि मुझे इस जवाब के लिए क्यों हटा दिया गया था ... –

0

यह शायद void Foo::foo(bar* const pBar) के बारे में ज्यादा परवाह नहीं करता है क्योंकि आप पॉइंटर के साथ कैसे व्यवहार करते हैं (कॉन्स्ट या नहीं) दिनचर्या के बाहर एक बिट से कोई फर्क नहीं पड़ता। सी नियम कहते हैं कि पीबीआर में कोई बदलाव किसी भी तरह से foo के बाहर यात्रा नहीं करेगा।

हालांकि, यदि यह (const bar* pBar) है, तो इससे कोई फर्क पड़ता है, क्योंकि इसका मतलब है कि संकलक कॉलर्स को पॉइंटर्स को गैर-कॉन्स ऑब्जेक्ट्स में पास करने की अनुमति नहीं देता है।

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