2010-10-28 24 views
10

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

class Foo 
{ 
    const int& First() const 
    { 
     return Second(); 
    } 

    int& Second() 
    { 
     return m_bar; 
    } 

    int m_bar; 
} 

मैं वास्तव में ऐसा करने के ज्ञान पर चर्चा नहीं करना चाहता हूं, अगर यह संभव हो तो मैं उत्सुक हूं।

+3

आप पहले व्यक्ति नहीं हैं: http://stackoverflow.com/questions/856542/elegant-solution-to-duplicate-const-and-non-const-getters –

+0

धन्यवाद जब तक यह नहीं आया मेरी खोज – Steve

उत्तर

28
return (const_cast<Foo*>(this))->Second(); 

फिर चुपचाप रोओ।

+0

सुझाता है कि क्या कार्य समान नाम हैं? कॉन्स int और GetBar() const; int और GetBar(); – phandinhlan

+0

आप स्थिरता पर एक फ़ंक्शन अधिभारित कर सकते हैं, इसलिए यह बस काम करेगा। – user3063349

10

यह संभव है:

const int& First() const 
{ 
    return const_cast<Foo*>(this)->Second(); 
} 

int& Second() { return m_bar; } 

मैं इस की सिफारिश नहीं होगा, यह बदसूरत और खतरनाक है (const_cast का कोई भी उपयोग खतरनाक है)।

सहायक कार्य में जितना सामान्य कार्यक्षमता बढ़ाना बेहतर है, उसके बाद आपके कॉन्स और गैर-कॉन्स सदस्य कार्य प्रत्येक के रूप में कम काम करते हैं।

इस तरह के एक साधारण एक्सेसर के मामले में, यह दोनों कार्यों से return m_bar; जितना आसान है जितना कि दूसरे से एक समारोह को कॉल करना है।

+0

या बस 'int और second()' को 'int और second() const' में बदलें। गैर-'const' सदस्य फ़ंक्शंस को 'द्वितीय()' को कॉल करने में कोई समस्या नहीं होगी, लेकिन अब 'const' सदस्य फ़ंक्शंस बिना किसी भी जिगर-पोकररी के कॉल कर पाएंगे। –

+0

@ जेरेमी: आप कैसे मानते हैं कि हम किसी सदस्य के लिए एक गैर-कॉन्स्ट संदर्भ वापस करते हैं? – GManNickG

+0

@GMan: Touché। आप 'm_bar' को 'mutable int' के रूप में घोषित किए बिना नहीं कर सकते। @ फ्रेड लार्सन की सिफारिश काफी अच्छी है, लेकिन जिस दिशा में यह आगे बढ़ता है - हर आशीर्वाद प्राप्तकर्ता को दो बार लिखना, एक बार 'कॉन्स्ट'-संशोधित और एक बार नहीं - इतना खुशहाली नहीं है। –

3

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

मुझे पता है कि आपने कहा था कि आप इसके बारे में नहीं सुनना चाहते थे, लेकिन मुझे लगता है कि इस प्रश्न पर होने वाले अन्य लोगों के लिए यह महत्वपूर्ण है। const पर

2

अधिभार:

const int& Second() const 
{ 
    return m_bar; 
} 

आप इस विधि जोड़कर उसे मूल गैर स्थिरांक संस्करण रख सकते हैं।

1

इटरेटर इस तरह के समान हैं और एक दिलचस्प अध्ययन करते हैं।

कॉन्स इटरेटर अक्सर 'गैर कॉन्स' इटरेटर्स के लिए आधार होते हैं, और आपको अक्सर const_cast<>() या सी शैली का उपयोग बच्चे के एक्सेसर्स के साथ बेस क्लास से कॉन्स्ट को त्यागने के लिए किया जाता है।

संपादित करें: टिप्पणी

मैं एक ज़िप इटरेटर जहां स्थिरांक एक गैर स्थिरांक

से विरासत है था यह आम तौर पर गलत inheritence संरचना (हो सकता है अगर आपके कह कि मैं क्या लगता है कि आप हैं), कारण यह है कि बच्चों को माता-पिता से कम प्रतिबंधित नहीं होना चाहिए।

का कहना है कि आपके पास अपने ज़िप इटरेटर लेने वाले कुछ एल्गोरिदम थे, क्या यह एक कॉन्स इटरेटर को गैर-कॉन्सेट में पास करने के लिए उचित होगा?

यदि आपके पास एक कॉन्स कंटेनर था, तो केवल इसे एक कॉन्स इटरेटर के लिए पूछ सकता था, लेकिन फिर कॉन्स्ट इटरेटर एक पुनरावर्तक से लिया गया है ताकि आप माता-पिता पर नॉन कॉन्स्ट एक्सेस के लिए केवल सुविधाओं का उपयोग कर सकें।

यहाँ पारंपरिक एसटीएल मॉडल

class ConstIterator: 
    public std::_Bidit< myType, int, const myType *, const mType & > 
{ 
    reference operator*() const { return m_p; } 
} 

class Iterator : public ConstIterator 
{ 
    typedef ConstIterator _Mybase; 
    // overide the types provided by ConstIterator 
    typedef myType * pointer; 
    typedef myType & reference; 

    reference operator*() const 
    { 
    return ((reference)**(_Mybase *)this); 
    } 
} 

typedef std::reverse_iterator<ConstIterator> ConstReverseIterator; 
typedef std::reverse_iterator<Iterator> ReverseIterator; 
+0

मैं सदस्य कार्यों की स्थिरता में हेरफेर करने के लिए टेम्पलेट कक्षाओं और प्रयुक्त प्रकार के लक्षणों के रूप में इसे लिखने के लिए लिखता हूं; यह 'const_cast' की आवश्यकता से बचाता है और कोड को पढ़ने में आसान बनाता है। –

+0

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

+0

यह वास्तव में इसके लिए मेरा उपयोग मामला था। मेरे पास एक ज़िप इटरेटर है जहां कॉन्स को गैर-कॉन्स से प्राप्त होता है। @ जेम्स, क्या आप इस प्रश्न का उत्तर टाइप गुणों के उत्तर के साथ दे सकते हैं? यदि संभव हो तो मुझे यह करने में वास्तव में दिलचस्पी नहीं है – Steve

0

मैंने पाया अपने आप को एक गैर-स्थिरांक सदस्य समारोह है कि विरासत में मिला था फोन करने की कोशिश कर निम्नलिखित सुझाव दिया inheritence की एक त्वरित रूपरेखा है, लेकिन एपीआई मैं था की वजह से वास्तव में स्थिरांक था का उपयोग करते हुए। आखिर में मैं एक अलग समाधान पर बस गया: एपीआई को दोबारा बातचीत करें ताकि मेरे द्वारा प्राप्त किया गया कार्य ठीक से हो।

दूसरों के कार्यों में परिवर्तनों पर बातचीत करना हमेशा संभव नहीं होगा, लेकिन जब संभव हो तो ऐसा करना const_cast का उपयोग करने की आवश्यकता से साफ और अच्छा लगता है और यह अन्य उपयोगकर्ताओं को भी लाभान्वित करता है।

3

कॉन्स सदस्य विधियों का प्रतिबंध संकलन समय से आया है। यदि आप कंपाइलर को मूर्ख बना सकते हैं, तो हाँ।

class CFoo 
{ 
public: 
    CFoo() {m_Foo = this;} 
    void tee(); 

    void bar() const 
    { 
     m_Foo->m_val++; // fine 
     m_Foo->tee(); // fine 
    } 
private: 
    CFoo * m_Foo; 
    int m_Val; 

}; 

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

+0

क्या एक डरावनी चाल है! ... मैं इसका इस्तेमाल करूंगा :) – Olumide

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