2011-11-30 13 views
8

मुझे अपनी कक्षा में एक कॉन्स विधि मिली है, जिसे गैर-कॉन्स में बदला नहीं जा सकता है। इस विधि में, मुझे एक गैर-कॉन्स विधि कॉल करने की आवश्यकता है लेकिन संकलक मुझे ऐसा करने नहीं देता है।किसी कॉन्स्ट विधि से गैर-कॉन्स्ट विधि को कैसे कॉल करें?

वहाँ इसके चारों ओर कोई तरीका है? यहाँ मेरी कोड का एक सरलीकृत नमूना है:

int SomeClass::someMethod() const { 
    QColor saveColor = color(); 
    setColor(QColor(255,255,255)); // Calling non-const method 

    // .... 

    setColor(saveColor); // restore color 

    return 1; 
} 
+3

क्या यह एक कॉन्स फ़ंक्शन होने के मुख्य नियम के खिलाफ नहीं होगा? – DumbCoder

+2

@ डंबकोडर, बाहर से, यह एक कॉन्स फ़ंक्शन है जिसमें क्लाइंट को दिखाई देने वाला कुछ भी नहीं बदला गया है। –

+0

एक गैर-कॉन्स्ट विधि का तात्पर्य है कि यह आपके ऑब्जेक्ट में कुछ डेटा बदल रहा है। यदि 'someMethod()' एक गैर-कॉन्स्ट विधि को कॉल करता है, तो यह अप्रत्यक्ष रूप से डेटा बदल रहा है। तो वास्तव में, 'कुछ विधि()' बस 'const' नहीं होना चाहिए। –

उत्तर

5

const -correctness करने का चुनौतियों में से एक आप इसे आधे रास्ते नहीं कर सकता है। यह सब कुछ या कुछ भी नहीं है। यदि आप इसे आधे रास्ते में करने का प्रयास करते हैं, तो आप यहां एक कठिन स्थान पर पहुंच जाते हैं जैसे आप यहां हैं। आप एक अच्छा const -correct वर्ग कुछ पागल पुराने द्वारा किया जा रहा है, आम तौर विरासत (या एक पुराने crummudgeon द्वारा लिखित) कोड है कि const -correct नहीं है के साथ खत्म हो और यह सिर्फ काम नहीं करता। आप सोच रहे हैं कि const - सहीता सभी परेशानी के लायक है।

I need to call a non-const method [from a const method] 

आप सीधे नहीं कर सकते हैं। न ही आपको चाहिए हालांकि, एक विकल्प है ...

जाहिर है आप const विधि से एक गैर-const विधि को कॉल नहीं कर सकते हैं। अन्यथा, सदस्य कार्यों पर लागू होने पर const का कोई अर्थ नहीं होगा।

const सदस्य फ़ंक्शन mutable चिह्नित सदस्य चर बदल सकता है, लेकिन आपने संकेत दिया है कि यह आपके मामले में संभव नहीं है।

आप SomeClass* me = const_cast<SomeClass*>(this); की तरह कुछ करने से दूर const सत्ता कास्ट करने के लिए प्रयास कर सकता है लेकिन ए) यह आमतौर पर यूबी में परिणाम होगा, या 2) यह const -correctness के पूरे विचार का उल्लंघन करती है।

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

#include <iostream> 
#include <string> 
using namespace std; 

class Gizmo 
{ 
public: 
    Gizmo() : n_(42) {}; 
    void Foo() const; 
    void Bar() { cout << "Bar() : " << n_ << "\n"; } 
    void SetN(int n) { n_ = n; }; 
    int GetN() const { return n_; } 
private: 
    int n_; 
}; 

void Gizmo::Foo() const 
{ 
    // we want to do non-const'y things, so create a proxy... 
    Gizmo proxy(*this); 
    int save_n = proxy.GetN(); 
    proxy.SetN(save_n + 1); 
    proxy.Bar(); 
    proxy.SetN(save_n); 
} 

int main() 
{ 
    Gizmo gizmo; 
    gizmo.Foo(); 
} 
+0

यह कैसे उपयोगी है? मैं उलझन में हूं। यहां प्रॉक्सी प्रॉक्सी नहीं है, क्योंकि यह मूल ऑब्जेक्ट का प्रतिनिधित्व नहीं करता है। यह केवल एक स्थानीय वस्तु है जिसमें कोई असाधारण शक्ति नहीं है। प्रॉक्सी के साथ काम करना मूल वस्तु के साथ काम करने के बराबर नहीं है। – Nawaz

+2

@ नवाज: अगर यह एक मानक-अनुकूल तरीके से अपना काम करने में मदद करता है, तो यह उपयोगी है। –

11

आप this सूचक पर const_cast इस्तेमाल कर सकते हैं,

int SomeClass::someMethod() const { 
    const_cast<SomeClass*>(this)->setColor(...);// Calling non-const method 
    //whatever 
} 

लेकिन आप अपरिभाषित व्यवहार में चलाने यदि आप ऐसा है कि एक वस्तु है कि था के लिए मूल रूप से const घोषित कर दिया।

तो यह:

SomeClass object; 
object.someMethod(); 

ठीक है, लेकिन यह:

const SomeClass object; 
object.someMethod(); 

अपरिभाषित व्यवहार अर्जित करता है।

वास्तविक समाधान यह है कि आपका const फ़ंक्शन पहले स्थान पर const नहीं होना चाहिए।

+1

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

5

किसी कॉन्स्ट विधि से गैर-कॉन्स्ट विधि को कैसे कॉल करें?

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

या, आपको कुछ और करना चाहिए, जिसके लिए आपको const फ़ंक्शन से गैर-कॉन्स्ट फ़ंक्शन को कॉल करने की आवश्यकता नहीं होगी। पसंद है, setColor फ़ंक्शन पर कॉल न करें? जैसे, एक से अधिक कार्यों में कॉन्स फ़ंक्शन को विभाजित करें (यदि आप ऐसा कर सकते हैं)? या कुछ और?

अपने विशेष मामले में, यदि setColor केवल कुछ सदस्य चर सेट, का कहना है कि m_color, तो आप यह mutable घोषणा कर सकते हैं:

mutable QColor m_color; 

और फिर अपने स्थिरांक समारोह में यह निर्धारित करते हैं, setColor फ़ंक्शन कॉल के बिना, और बिना const_cast कर रहा है।

+0

यह प्रश्न का उत्तर नहीं है जैसा कि मैंने अभी लिखा है, मैं इसे गैर-कॉन्स में नहीं बदल सकता। –

+0

@Laurent: संपादन देखें। – Nawaz

+2

@Laurent, संभावित रूप से आप कर सकते हैं, अगर आप सदस्यों को उस म्यूटेबल 'में स्पर्श कर सकते हैं? – Nim

6

आप एक const अंदर कुछ आंतरिक स्थिति को बदलने के लिए -method आप भी प्रभावित राज्य mutable घोषणा कर सकते हैं की आवश्यकता होती है:

class Foo { 
public: 
    void doStuff() const { bar = 5; } 
private: 
    mutable int bar; 
}; 

इस मामले हैं, जहां आप अपने वर्ग के सदस्य के रूप में mutexes की तरह सामान है के लिए है। एक म्यूटेक्स प्राप्त करना और जारी करना क्लाइंट-दृश्य स्थिति को प्रभावित नहीं करता है, लेकिन const -method में तकनीकी रूप से वर्जित है। समाधान mutex mutable को चिह्नित करना है। आपका मामला समान दिखता है, हालांकि मुझे लगता है कि इस वर्ग के लिए इस समाधान के लिए कुछ रिफैक्टरिंग की आवश्यकता है।

इसके अलावा, आप this answer पढ़ने के लिए देखने के लिए कैसे आप आरए II का उपयोग कर यह अस्थायी स्थिति-परिवर्तन अपवाद-सुरक्षित बना सकते हैं चाहते हो सकता है।

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