2014-10-24 8 views
8

मान लीजिए मैं एक वर्ग फू के लिए एक निजी सूचक है कि एक बार:क्या यह एक चालक कन्स्ट्रक्टर में स्थिरता को दूर करने के लिए स्वीकार्य है?

class Foo 
{ 
private: 
    Bar * bar; 

public: 
    Foo() : bar (new Bar()) 
    {} 

    ~Foo() 
    { 
    delete bar; 
    } 
}; 

सूचक bar कभी नहीं एक अलग उदाहरण को सौंप दिया जाना चाहिए, तो यह समझ में सूचक ही बनाने के लिए बनाता है क्रम में const मुझे (या एक मेंटेनर) भविष्य में ऐसा करने से रोकने के लिए:

private: 
    Bar * const bar; 

मैं यह कर रहा पसंद जहाँ भी अवसर मिले।

मैं तो एक कदम निर्माता लिखना चाहते थे, तो यह कुछ इस तरह दिखेगा:

Foo (Foo && f) : 
    bar (f.bar) 
{ 
    f.bar = NULL; // uh oh; f.bar is const. 
} 

मैं या तो f.bar की constness दूर कास्टिंग द्वारा या यह नहीं बना द्वारा "त्रुटि दूर जाने" कर सकते हैं पहली जगह में बांधो। इनमें से कोई भी चीज नहीं है जो मैं करना चाहता हूं। मैं पूरी तरह से कॉन्स को नहीं हटाऊंगा क्योंकि यह किसी कारण से है। दूसरी ओर, मेरे लिए स्थिरता रिंग अलार्म घंटी कास्टिंग और कुछ ऐसा है जो मैं आमतौर पर नहीं करता हूं। मेरा सवाल है: क्या इसे इस तरह के एक चालक कन्स्ट्रक्टर के भीतर स्थिरता को दूर करने के लिए स्वीकार्य अभ्यास माना जाता है? क्या कोई बेहतर तरीका है जिसे मैंने नहीं माना है?

मुझे नहीं लगता कि मेरे सवाल यह वैसा ही है जैसा: Use const_cast to implement the move constructor

+7

यदि आपको 'बार' को बदलने की आवश्यकता है तो स्पष्ट रूप से यह 'const' नहीं होना चाहिए। अपने डिजाइन के बारे में सावधानी से सोचें। – user657267

+0

ऐसा लगता है कि आपकी कक्षा को चलने योग्य नहीं होना चाहिए। – juanchopanza

+2

यहां const_cast का उपयोग अपरिभाषित व्यवहार है। –

उत्तर

6

यदि आपको किसी मामले में पॉइंटर बदलना होगा (भले ही यह केवल एक ही मामला है), तो शायद यह const नहीं होना चाहिए।

हालांकि, किसी ऑब्जेक्ट से स्थिरता को हटाने के लिए const_cast का उपयोग करके, और फिर कास्ट के नतीजे का उपयोग करके अपरिभाषित व्यवहार का उपयोग करके इस विचार को अलग रखा गया। यह केवल const_cast एक चर है जो मूल रूप से कॉन्स्ट नहीं था। यदि संभव हो

+1

अधिक सटीक, यह कास्ट के परिणाम को लिखने के लिए अपरिभाषित व्यवहार है। आप अभी भी परिणाम से पढ़ सकते हैं। –

+0

मुझे लगता है कि यह सबक एक बात है जिसे मैंने इस साल सीखा है कि मैंने सही बनाम अपरिपक्व-व्यवहार-उत्तेजक उपयोग के बारे में const_cast का उपयोग किया है: "किसी वैरिएबल को कभी भी संशोधित न करें जिसका घोषणा है।" – paercebal

4

आप मूल रूप से अपने आप को खंडन कर रहे हैं।
आप कह रहे हैं "मैं इसे किसी भी परिस्थिति में बदलना नहीं चाहता हूं", और आप कह रहे हैं "जब मैं किसी वस्तु को स्थानांतरित करता हूं तो मैं इसे बदलना चाहता हूं"।

तो, यदि कोई परिदृश्य है जहां इसे बदलने की जरूरत है, तो यह const नहीं है, और आप इसे आसानी से हटा सकते हैं।

यदि आप निर्धारित हैं कि आप इसे const चाहते हैं, तो आप एक और बूलियन मान जोड़ सकते हैं जो स्वामित्व निर्धारित करता है (यदि आपको संसाधन जीवनकाल को संभालने की आवश्यकता है)। तो बिंदु वस्तु केवल तभी जारी की जा सकती है जब ऑब्जेक्ट का मालिक बनने वाले विनाशक को बुलाया जाता है।

+0

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

+2

यह दिखाता है कि आपके डिज़ाइन में कोई दोष है। एक मामला है जहां वह सूचक बदल सकता है। उदाहरण: '{फू एफ; फू एफ 2 (एसडीडी :: चाल (एफ)); f.somefn(); } ' उस कोड स्निपेट के साथ स्वाभाविक रूप से कुछ भी गलत नहीं है, लेकिन कुछ एफएन() को अपरिवर्तित होने के बराबर बार के मूल्य पर भरोसा करने में सक्षम होना चाहिए। आप संकलक (और आपके कोड के भविष्य के पाठकों) को बहुत स्पष्ट रूप से बताया था कि एक बार बार शुरू किया गया है, यह _never_ बदल जाएगा। लेकिन क्योंकि वस्तु को स्थानांतरित कर दिया गया था, यह बदल गया। इस प्रकार सदस्य की कॉन्स्टेस का उल्लंघन करना। –

+0

@AndreKostur यह एक महान स्पष्टीकरण है, धन्यवाद। यह दिखाता है कि "चलने योग्यता" केवल एक चालक कन्स्ट्रक्टर जोड़ने से कहीं अधिक है। सभी सदस्य कार्यों में किसी ऑब्जेक्ट का व्यवहार * पोस्ट चाल * पर विचार किया जाना चाहिए। – peterpi

3

, unique_ptr बजाय का उपयोग करें:

std::unique_ptr<Bar> bar; 
Foo(Foo&& f) : bar(std::move(f.bar)){} 
// or maybe you won't even have to declare move constructor 

इस तरह न केवल आप और अधिक सुरक्षा और आराम मिल जाएगा, लेकिन यह भी आप गलती से = साथ यह पुनर्लेखन नहीं होगा, तो आप .reset() फोन करना होगा तो आप इसे करने से पहले दो बार सोचेंगे (जो आपका लक्ष्य है, मुझे लगता है)।

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

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