2009-11-25 21 views
9

मेरे पास कक्षा का सदस्य मेरा सदस्य है जो myType पॉइंटर है। मैं इस सदस्य को ऐसे फ़ंक्शन में असाइन करना चाहता हूं जिसे कॉन्स के रूप में घोषित किया गया हो। मैं इस प्रकार कर रहा हूँ:एक कॉन्स फ़ंक्शन में सदस्य असाइनमेंट

void func() const 
{ 
    ... 
    const_cast<myType*>(myMember) = new myType(); 
    ... 
} 

इस कुलपति में ++ ठीक काम करता है कर रहा है, लेकिन जीसीसी संदेश "काम की बाईं संकार्य के रूप में आवश्यक lvalue" के साथ एक त्रुटि देता है।

सदस्य बनाना उत्परिवर्तनीय मुझे केवल const_cast को हटाने और मान असाइन करने की अनुमति देता है। हालांकि, मुझे पूरी तरह से यकीन नहीं है कि यह अन्य दुष्प्रभावों के साथ आता है।

क्या मैं सदस्य को उत्परिवर्तनीय बनाने के बिना अपना सदस्य असाइन कर सकता हूं? कैसे? सदस्यों को उत्परिवर्तनीय बनाने में कोई दुष्प्रभाव हैं?

उत्तर

8

कोड अभ्यस्त वास्तव में कुलपति में ++ काम करते हैं - आप मूल्य को अद्यतन करने नहीं कर रहे हैं (या कम से कम यह नहीं होना चाहिए), इसलिए जीसीसी से चेतावनी। [: पी अन्य प्रतिक्रिया से, धन्यवाद]: सही कोड

const_cast<myType*&>(myMember) = new myType(); 

या है

const_cast<ThisType*>(this)->myMember = new myType(); 

बनाना यह परिवर्तनशील प्रभावी रूप से मतलब है कि आप जो आम तौर पर है कि तुम क्या होना चाहिए const सदस्य कार्यों में निहित const_cast रों मिलता है, जब आप अपने आप को एस this पर लोड करते हैं तो आप की ओर बढ़ते रहें। इसके अलावा अन्य 'उत्परिवर्तनीय उपयोग करने के लिए दुष्प्रभाव' नहीं हैं।

जैसा कि आप इस प्रश्न को घेरते हुए जोरदार बहस से देख सकते हैं, mutable का बहुत उपयोग नहीं है और const_cast के बहुत सारे उपयोग निश्चित रूप से आपके कोड में खराब गंध के लक्षण हो सकते हैं। एक वैचारिक दृष्टिकोण से, स्थिरता कास्टिंग या mutable का उपयोग करके बहुत अधिक प्रभाव हो सकते हैं। कुछ मामलों में, सही काम करने के लिए विधि को गैर-कॉन्स में बदलने के लिए हो सकता है, यानी, इस तथ्य के स्वामित्व में कि यह राज्य को संशोधित कर रहा है।

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

+0

धन्यवाद। [न्यूनतम 15 वर्ण] –

+1

मुझे लगता है कि यह काम करता है, यह संभवतः सबसे खराब समाधान है। यह सदस्य समारोह में एक कॉन्स-कास्ट में क्या होता है (एक अपरिवर्तनीय उदाहरण की आंतरिक स्थिति को बदलता है) पूरी तरह छुपाता है। "mutable" स्पष्ट होगा (या इंटरफेस का उपयोग कर)। –

+1

कॉन्सनेस दूर कास्टिंग अपरिभाषित व्यवहार की ओर जाता है। अपने जोखिम पार इस्तेमाल करें। विधि को गैर स्थिर बनाने के लिए एक बेहतर समाधान होगा। –

17

यह परिदृश्य - एक आंतरिक आंतरिक स्थिति परिवर्तन जो बाह्य स्थिति को प्रभावित नहीं करता है (उदाहरण के लिए कैशिंग परिणाम) - बिल्कुल mutable कीवर्ड है।

+1

यदि आप केवल एक कॉन्स-विधि में सदस्य को लेखन पहुंच प्राप्त करना चाहते हैं तो म्यूटेबल अच्छा तरीका नहीं है। – Staseg

+4

किसी म्यूटेबल ऑब्जेक्ट को लिखते समय ऑब्जेक्ट की बाहरी रूप से देखने योग्य स्थिति में बदलाव नहीं होना चाहिए। एक कॉन्स्ट फ़ंक्शन में किसी त्रुटि को बाधित करने के लिए एक सदस्य उत्परिवर्तनीय बनाना वैध नहीं है यदि परिवर्तन बाहरी रूप से दिखाई देता है, और अपरिभाषित व्यवहार का कारण बन सकता है। उत्परिवर्तनीय के वैध उपयोग में कैशिंग शामिल है, उदाहरण के लिए, एक ही कॉल दो बार एक ही परिणाम देता है, लेकिन तेज़। – AshleysBrain

5
class Class{ 
int value; 
void func()const{ 
const_cast<Class*>(this)->value=123; 
} 
}; 
+0

आपको किसी सदस्य के बजाय कास्ट ऑब्जेक्ट चाहिए। – Staseg

+0

धन्यवाद। मैं रूबेन के पहले कोड से जा रहा हूं क्योंकि यह क्लीनर दिखता है। अगर मैं कर सकता, तो मैं दोनों को "उत्तर" के रूप में चिह्नित करता। –

6

const_cast लगभग हमेशा डिजाइन विफलता का संकेत है। आपके उदाहरण में, func()const नहीं होना चाहिए, या myMembermutable होना चाहिए।

func() का एक कॉलर उसकी वस्तु को बदलने की उम्मीद नहीं करेगा; लेकिन इसका मतलब है "जिस तरह से वह नोटिस कर सकती है उसे बदलने के लिए नहीं"; यह है, अपने बाहरी राज्य को बदलने के लिए नहीं।यदि myMember बदलना ऑब्जेक्ट बाहरी स्थिति को नहीं बदलता है, तो mutable कीवर्ड है; अन्यथा, func()const नहीं होना चाहिए, क्योंकि आप अपने फ़ंक्शन गारंटी को धोखा दे रहे होंगे।

याद रखें कि mutable सर्क्यूनेंट कॉन्स्ट-शुद्धता के लिए एक तंत्र नहीं है; यह इसे सुधारने के लिए एक तंत्र है।

+1

+1 "const_cast लगभग हमेशा डिजाइन विफलता का संकेत है" –

+0

^हां, और कभी-कभी विफलता उस लाइब्रेरी में होती है जिसका आप उपयोग कर रहे हैं! मैं एक का उपयोग करता हूं जो पॉइंटर-टू-गैर-'const' लेता है लेकिन (और मैं इसे नियमित रूप से जांचता हूं :) ऑब्जेक्ट को म्यूटेट नहीं करता है। इस ज्ञान में सुरक्षित, इसलिए मैं लाइब्रेरी में किसी भी 'Obj const & '(अस्थायी समेत) को पास कर सकता हूं, मैं इसे एक ऐसे फ़ंक्शन में लपेटता हूं जो' const_cast (& constObj) 'करता है। बदसूरत, शायद - लेकिन वास्तव में 'Obj' के साथ क्या होता है की वास्तविकता के लिए truer और मुझे लाइब्रेरी के साथ बेहतर चीजें करने की अनुमति देता है ... कम से कम जब तक लेखक सी [+] सी #+ से अधिक का उपयोग करने का फैसला करता है [sigh] –

+0

@underscore_d यह एक है 'const_cast' के वैध उपयोगों के: अपूर्ण सी ++ से निपटना। अगर मेरे पास प्रत्येक पॉन्टर-टू-गैर-कॉन्स के लिए एक प्रतिशत था जो दुनिया में पॉइंटर-टू-कॉन्स्ट होना चाहिए ... – Gorpik

1

स्टीव गिलहम ने लिखा, mutable आपके प्रश्न का सही (और संक्षिप्त) उत्तर है। मैं बस आपको एक अलग दिशा में एक संकेत देना चाहता हूँ। शायद आपके szenario में एक (या एक से अधिक) इंटरफ़ेस का उपयोग करना संभव है? शायद आप यह निम्न उदाहरण से grok कर सकते हैं:

class IRestrictedWriter // may change only some members 
{ 
public: 
    virtual void func() = 0; 
} 

class MyClass : virtual public IRestrictedWriter 
{ 
public: 
    virtual void func() 
    { 
    mValueToBeWrittenFromEverybody = 123; 
    } 

    void otherFunctionNotAccessibleViaIRestrictedWriter() 
    { 
    mOtherValue1 = 123; 
    mOtherValue2 = 345; 
    } 

    ... 
} 

इसलिए, यदि आप कुछ समारोह एक IRestrictedReader * बजाय एक const MyClass * के पास यह func फोन और इस तरह बदल mValueToBeWrittenFromEverybody जबकि mOtherValue1 तरह का "स्थिरांक" है सकते हैं।

। मुझे mutable हमेशा एक हैक का थोड़ा सा लगता है (लेकिन इसे कभी-कभी उपयोग करें)।

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