2010-10-08 18 views
26

अगर यह पूछा गया है, तो मैं क्षमा चाहता हूं, लेकिन मैं C++ में सदस्य फ़ंक्शन कैसे बना सकता हूं जो निम्न scenerios में एक सूचक देता है: 1. लौटा हुआ सूचक स्थिर है, लेकिन अंदर जंक को संशोधित किया जा सकता है। 2. अंदर जंक स्थिर है लेकिन लौटा सूचक संशोधित किया जा सकता है। 3. न तो जंक, न ही सूचक को संशोधित किया जा सकता है।सी ++ कॉन्स सदस्य फ़ंक्शन जो एक कॉन्स पॉइंटर लौटाता है .. लेकिन किस प्रकार का कॉन्स लौटा हुआ पॉइंटर है?

यह इतना की तरह है:

  1. int *const func() const
  2. const int* func() const
  3. const int * const func() const

ट्यूटोरियल मैं इस तरह के अंतर को कवर नहीं पढ़ा है सब के सब।

साइड नोट: मेरी विधि स्थिरांक घोषित किया जाता है तो ट्यूटोरियल कहना है कि मैं यह कहते हुए कर रहा हूँ कि मैं मानकों को संशोधित नहीं होगा .. लेकिन यह स्पष्ट नहीं है पर्याप्त मेरे लिए इस मामले में जब एक पैरामीटर एक सूचक है है । क्या मेरे पैरामीटर इस तरह होने की आवश्यकता है:

ए। void func(const int* const x) const;
बी। void func(const int* x) const;
सी। void func(const int* const x) const;

+0

का संयोजन है, लेकिन वर्ग चर को संशोधित करने के बारे में अधिक। – Jor

उत्तर

53

मैं नहीं जानता कि क्या आप जिस पुस्तक को पढ़ा है, लेकिन अगर आप एक विधि स्थिरांक निशान इसका मतलब है कि thisMyClass* है, जो अपनी बारी में मतलब है कि आप nonstatic डेटा सदस्य हैं कि नहीं बदल सकते हैं के बजाय प्रकार const MyClass* का हो जाएगा mutable घोषित नहीं किया गया है, न ही आप this पर किसी भी गैर-कॉन्स्ट विधियों को कॉल कर सकते हैं।

अब वापसी मूल्य के लिए।

1। int * const func() const

फ़ंक्शन स्थिर है, और लौटा हुआ सूचक स्थिर है लेकिन 'अंदर जंक' को संशोधित किया जा सकता है। हालांकि, मैं एक स्थिरांक सूचक लौटने क्योंकि परम समारोह कॉल एक rvalue हो जाएगा, और गैर-वर्ग प्रकार के rvalues ​​const नहीं किया जा सकता, जिसका अर्थ है कि const वैसे भी

2 नजरअंदाज कर दिया जाएगा का कोई मतलब नहीं देखते हैं। const int* func() const

यह एक उपयोगी बात है। "जंक अंदर" को

3 संशोधित नहीं किया जा सकता है। const int * const func() const

शब्दार्थ लगभग एक ही 2 के रूप में, 1.

में कारणों की HTH

+1

मुझे लगता है कि आप इस उत्तर में उपयोगी जानकारी के एक जोड़े टुकड़े है, लेकिन .. मेरे सवाल अभी भी बना हुआ है, तो मैं एक सदस्य विधि स्थिरांक, क्या हूँ मैं आवश्यक * बनाने * मेरी विधि हस्ताक्षर के रूप में है। अगर मैं आपको समझ नहीं पा रहा हूं तो मैं क्षमा चाहता हूं – Jor

+1

@ जोर: आप फ़ंक्शन हस्ताक्षर के बाकी प्रतिबंधों के लिए _required_ नहीं हैं। नोट करने के लिए केवल एक चीज है कि एक 'const' विधि में' 'this' const' के लिए सूचक है, इसलिए यदि आप सूचक द्वारा एक सदस्य वापसी या या तो वापसी मान संदर्भ संदर्भ या एक' const' प्रकार के सूचक होना जरूरी होता है या आपको संभावित रूप से खतरनाक 'const_cast' करना होगा। –

+1

@ जोर: जो कहना है, वापसी का प्रकार आप जो लौट रहे हैं उस पर निर्भर करता है। यदि आप किसी वर्ग सदस्य का पता वापस कर रहे हैं, तो वह सदस्य एक कॉन्स्ट सदस्य फ़ंक्शन के भीतर है, इसलिए आप विकल्प (2) चाहते हैं। –

9

कारण स्थिरांक में से कुछ का उपयोग करता है वास्तव में बहुत मतलब नहीं है।

मान लीजिए आप निम्नलिखित कार्य हो:

void myFunction (const int value); 

स्थिरांक संकलक कि मूल्य समारोह के अंदर परिवर्तन नहीं करना चाहिए बताता है। इस जानकारी के पास कॉलर के लिए कोई मूल्य नहीं है।मूल्य के साथ क्या करना है यह तय करने के लिए यह कार्य स्वयं पर निर्भर है। फोन करने वाले के लिए, निम्न दो कार्यशील परिभाषाएँ वास्तव में उसके लिए एक ही व्यवहार करते हैं:

void myFunction (const int value); 
void myFunction (int value); 

क्योंकि मूल्य मूल्य से पारित हो जाता है, जिसका अर्थ है समारोह वैसे भी एक स्थानीय प्रति हो जाता है कि।

दूसरी ओर, यदि तर्क एक संदर्भ या सूचक है, तो चीजें बहुत अलग हो जाती हैं।

void myFunction (const MyClass &value); 

यह फोन करने वाले है कि मूल्य संदर्भ द्वारा पारित कर दिया है बताता है (ताकि स्क्रीन के पीछे यह वास्तव में एक सूचक है), लेकिन फोन करने वाले मान बदलने के लिए नहीं वादा करता है। एक ही संकेत के लिए सच है:

void myFunction (const MyClass *value); 

हम (क्योंकि प्रदर्शन के कारणों का) MyClass के सूचक के पास, लेकिन समारोह मान बदलने के लिए नहीं वादा करता है।

, तब हम निम्नलिखित लिखना होगा:

void myFunction (MyClass * const value); 

फिर हम वापस वह पूर्णांक पहले स्थिति है। myFunction एक सूचक मिलता है, जो मूल्य से गुजरता है, और जो स्थिर है। चूंकि माईफंक्शन को सूचक मूल्य की प्रति प्राप्त होती है, इसलिए यह कॉलर के लिए कोई फर्क नहीं पड़ता कि यह स्थिर है या नहीं। सबसे महत्वपूर्ण बात यह है कि मेरा कार्य मूल्य की सामग्री को बदल सकता है, क्योंकि पॉइंटर चर स्वयं ही स्थिर है, लेकिन इसमें सामग्री नहीं है।

ही वापसी मूल्यों के लिए सच है:

const double squareRoot(double d); 

यह किसी भी मतलब नहीं है। स्क्वायर रूट एक कॉन्स डबल देता है लेकिन चूंकि इसे 'मूल्य से' पारित किया जाता है, और इस प्रकार मुझे अपने स्थानीय चर में कॉपी करने की आवश्यकता होती है, मैं जो कुछ भी चाहता हूं वह कर सकता हूं।

दूसरी ओर:

const Customer *getCustomer(char *name); 

मुझसे कहता है कि getCustomer मुझे एक ग्राहक के लिए सूचक देता है, और मैं ग्राहक की सामग्री को बदलने की अनुमति नहीं कर रहा हूँ।

const Customer *getCustomer(const char *name); 
+0

ठीक है, मैं पैट्रिक को समझना शुरू कर रहा हूं, और मुझे एहसास हुआ कि कक्षा के सदस्यों को संशोधित न करने के साथ एक कॉन्स विधि को करना है .. तो उसे भूल जाओ। लेकिन मुझे आपका जवाब पसंद है, तो हो सकता है कि आप इनका जवाब दे सकें: "ग्राहक ग्राहक * प्राप्त करें ग्राहक (char * name);" आपने कहा कि कॉलर परिणाम संशोधित नहीं कर सकता है। लेकिन क्या यह मामला है कि वे रिटर्न वैरिएबल के माध्यम से परिणाम संशोधित नहीं कर सकते हैं, लेकिन अगर वे उस पॉइंटर को किसी अन्य पॉइंटर पर कॉपी करते हैं तो वे * सामग्री को संशोधित कर सकते हैं? – Jor

+0

और यहां एक और सवाल है। एक कॉन्स विधि उसके क्लास सदस्यों को पॉइंटर वापस नहीं कर सकती है जब तक कि यह एक कॉन्स पॉइंटर नहीं है .. लेकिन किस प्रकार का कॉन्स्ट पॉइंटर होना चाहिए? 1: कॉन्स * int 2: const * const int 3: int * const – Jor

+0

यदि आप "ग्राहक * प्राप्तकर्ता कस्टमर()" फ़ंक्शन को "ग्राहक *" चर में फ़ंक्शन मान असाइन करते हैं, तो आप इसे बदल पाएंगे ग्राहक की सामग्री हालांकि, सी ++ संकलक, इस काम पर एक त्रुटि देता है के बाद से आप सामान्य रूप से, एक गैर स्थिरांक-सूचक के लिए एक स्थिरांक-सूचक आवंटित करने के लिए अनुमति नहीं है क्योंकि इससे आपको पता 'अतिरिक्त अधिकार' अनुदान (अर्थात्: की सामग्री को बदलने के लिए सक्षम किया जा रहा ग्राहक)। हालांकि कुछ मामलों में (विशेष रूप से जब पुराने शुद्ध सी कोड से निपटने के लिए), तो आपको इसे रोकने की आवश्यकता हो सकती है, और फिर आपको एक const_cast का उपयोग करना चाहिए। – Patrick

0

स्थिरांक विधि आप को संशोधित करने से रोकता है:

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

चूंकि सूचक मूल्य (प्रतिलिपि) द्वारा वापस लौटाया जाता है, तो कॉलर कक्षा के सूचक सदस्य को संशोधित करने के लिए इसका उपयोग नहीं कर सकता है। इसलिए वापसी मूल्य में आधार जोड़ना कुछ भी नहीं जोड़ता है।

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

उदाहरण:

class X 
{ 
    int* p; 
public: 
    int* get_copy_of_pointer() const //the returned value is a copy of this->p 
    { 
     *p = 42; //this being const doesn't mean that you can't modify the pointee 
     //p = 0; //it means you can't modify the pointer's value 
     return p; 
    } 
    int* const& get_reference_to_pointer() const //can't return a reference to non-const pointer 
    { 
     return p; 
    } 
}; 
1

स्थिरांक के सूचक के रिटर्निंग भावना का एक बहुत बनाता है, लेकिन एक स्थिरांक सूचक लौट (आप संशोधित नहीं कर सकते) आम तौर पर कोई मूल्य कहते हैं (हालांकि कुछ कहते हैं कि यह उपयोगकर्ता त्रुटियों को रोकने या संकलक जोड़ सकते हैं अनुकूलन)।

ऐसा इसलिए है क्योंकि वापसी मूल्य फ़ंक्शन के कॉलर से संबंधित है, यानी यह उनकी स्वयं की प्रति है, इसलिए इससे कोई फर्क नहीं पड़ता कि वे इसे संशोधित करते हैं (कुछ और इंगित करने के लिए)। हालांकि सामग्री कॉलर को "संबंधित" नहीं है और फ़ंक्शन के कार्यान्वयनकर्ता एक अनुबंध कर सकता है कि यह केवल पढ़ने योग्य जानकारी है।

कॉन्स सदस्य कार्य कक्षा का राज्य बदलने की वादा नहीं करता है, हालांकि यह संकलक द्वारा वास्तविकता में जरूरी नहीं है। मैं यहाँ कॉन्स्ट_कास्ट या म्यूटेबल सदस्यों को इस तथ्य के रूप में संदर्भित नहीं कर रहा हूं कि यदि आपकी कक्षा में पॉइंटर्स या संदर्भ शामिल हैं, तो एक कॉन्स्ट सदस्य फ़ंक्शन आपके पॉइंटर्स को निरंतर पॉइंटर्स में बदल देता है लेकिन उन्हें पॉइंटर्स को कॉन्स्ट्रेंस नहीं करता है, वैसे ही आपके संदर्भ नहीं बदले जाते हैं संदर्भ-से-कॉन्स में। यदि ये आपकी कक्षा के घटक हैं (और ऐसे घटकों को अक्सर पॉइंटर्स द्वारा दर्शाया जाता है) तो आपके कार्य उनके राज्य को बदल सकते हैं।

उत्परिवर्ती सदस्य आंतरिक स्थिति को बदलने के दौरान आपकी कक्षा को बदलने की अनुमति देने के लाभ के लिए वहां हैं। इन्हें आमतौर पर लागू किया जा सकता है:

  • म्यूटेक्स जिन्हें आप पढ़ने के लिए भी लॉक करना चाहते हैं।
  • डेटा जो आलसी लोड होता है, यानी पहली बार उन्हें एक्सेस किया जाता है।
  • संदर्भ-गणना की गई वस्तुएं: यदि संदर्भ में कोई अन्य दर्शक है तो आप संदर्भ गणना को बढ़ाना चाहते हैं, इस प्रकार आप इसे पढ़ने के लिए अपने राज्य को संशोधित करते हैं।

const_cast को आम तौर पर "हैक" माना जाता है और अक्सर ऐसा किया जाता है जब किसी और ने अपना कोड ठीक से सही नहीं लिखा है। यह निम्न परिस्थितियों में हालांकि मान हो सकता है:

  • एकाधिक भार के जहां एक स्थिरांक है और एक गैर-स्थिरांक और स्थिरांक एक स्थिरांक-संदर्भ देता है और गैर स्थिरांक एक गैर स्थिरांक संदर्भ देता है, लेकिन अन्यथा वह एक जैसे है। कोड को डुप्लिकेट करना (यदि यह एक साधारण डेटा सदस्य नहीं है) एक अच्छा विचार नहीं है, तो दूसरे के संदर्भ में एक को कार्यान्वित करें और कंपाइलर के आसपास होने के लिए const_cast का उपयोग करें।

  • जहां आप विशेष रूप से कॉन्स्ट अधिभार को कॉल करना चाहते हैं लेकिन एक गैर-कॉन्स्ट संदर्भ है। पहले इसे कास्ट करने के लिए इसे कास्ट करें।

4

int *const func() const

आप कुछ मामलों

  • func का पता ले रहा है के अलावा यहां const का पालन नहीं कर सकते हैं।
  • सी ++ 0x में, func को decltype ऑपरेंड के रूप में फ़ंक्शन-कॉल सिंटैक्स के साथ सीधे कॉल करके int * const मिलेगा।

इसका कारण यह है कि आप एक शुद्ध सूचक मान, कि वास्तव में एक सूचक चर में संग्रहीत नहीं एक सूचक मूल्य कहने के लिए है।इस तरह के मूल्य योग्य नहीं हैं क्योंकि वे वैसे भी बदला नहीं जा सकता है। यदि आप const निकालते हैं तो भी आप obj.func() = NULL; नहीं कह सकते हैं। दोनों मामलों में, अभिव्यक्ति obj.func() प्रकार int* है और गैर-परिवर्तनीय (कोई जल्द ही मानक बोली और शब्द "rvalue" के साथ ऊपर आ जाएगा) है।

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

const int* func() const

यह आप आमतौर पर अगर शरीर return &this->intmember; की तरह कुछ होगा क्या करेंगे है। यह *obj.func() = 42; करके int सदस्य को बदलने की अनुमति नहीं देता है।

const int * const func() const

यह महसूस किया कि स्थिरांक सदस्य funcs संशोधित मानकों के साथ कुछ नहीं करना सिर्फ पहले दो :)

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