कॉपी कंस्ट्रक्टर को अक्षम करें


173

मुझे कक्षा में जाना है :

class SymbolIndexer {
protected:
  SymbolIndexer ( ) { }

public:
  static inline SymbolIndexer & GetUniqueInstance ( ) 
  { 
    static SymbolIndexer uniqueinstance_ ;
    return uniqueinstance_ ; 
  }
};

कोड को अक्षम करने के लिए मुझे इसे कैसे संशोधित करना चाहिए:

SymbolIndexer symbol_indexer_ = SymbolIndexer::GetUniqueInstance ( );

और केवल कोड की अनुमति दें जैसे:

SymbolIndexer & ref_symbol_indexer_ = SymbolIndexer::GetUniqueInstance ( );

1
Btw, क्या यह वंशानुक्रम (संरक्षित) के प्रावधानों के साथ एक सिंगलटन है?
आर। मार्टिनो फर्नांडिस

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

जवाबों:


286

आप कॉपी कंस्ट्रक्टर को निजी बना सकते हैं और कोई कार्यान्वयन प्रदान नहीं कर सकते हैं:

private:
    SymbolIndexer(const SymbolIndexer&);

या C ++ 11 में, स्पष्ट रूप से मना करें:

SymbolIndexer(const SymbolIndexer&) = delete;

43
deleteकीवर्ड के बारे में मैं निम्नलिखित जोड़ना चाहूंगा। एक नए वर्ग को डिजाइन करते समय मेरी मौजूदा आदत आदत है कि वह deleteतुरंत कॉपी कंस्ट्रक्टर और असाइनमेंट ऑपरेटर दोनों को दे। मैंने पाया है कि, संदर्भ के आधार पर, वे ज्यादातर अनावश्यक हैं और उन्हें हटाना अप्रत्याशित व्यवहार के कुछ मामलों को रोकता है। यदि एक स्थिति होती है जहां एक प्रतिलिपि ctor की आवश्यकता हो सकती है, तो निर्धारित करें कि क्या इसे स्थानांतरित शब्दार्थ के साथ किया जा सकता है। यदि यह अवांछनीय है, तो प्रतिलिपि ctor और असाइनमेंट ऑपरेटर दोनों के लिए एक कार्यान्वयन प्रदान करें। क्या यह एक अच्छा तरीका है जो मैं पाठक तक छोड़ूंगा।
pauluss86

1
@ pauluss86 मुझे आपका दृष्टिकोण पसंद है लेकिन मैं पूरी तरह से इसके लिए प्रतिबद्ध नहीं हूं क्योंकि मुझे लगता है कि इस पैटर्न का पालन करने में लगने वाला समय त्रुटियों को रोकने वाले समय की तुलना में अधिक है। जब भी मुझे यकीन नहीं होता मैं बस कॉपी को मना करता हूं।
टॉम ज़ातो -

@ pauluss86 यह मूल रूप से रस्ट क्या करता है: मूव-बाय-डिफॉल्ट (और कॉन्स्ट-बाय-डिफॉल्ट)। मेरी राय में बहुत मददगार।
कपिचु

33

यदि आपको एक से अधिक वंशानुक्रम का बुरा नहीं लगता (यह उतना बुरा नहीं है, सब के बाद), तो आप निजी कॉपी कंस्ट्रक्टर और असाइनमेंट ऑपरेटर के साथ सरल वर्ग लिख सकते हैं और इसके अतिरिक्त उपवर्ग:

class NonAssignable {
private:
    NonAssignable(NonAssignable const&);
    NonAssignable& operator=(NonAssignable const&);
public:
    NonAssignable() {}
};

class SymbolIndexer: public Indexer, public NonAssignable {
};

GCC के लिए यह निम्नलिखित त्रुटि संदेश देता है:

test.h: In copy constructor ‘SymbolIndexer::SymbolIndexer(const SymbolIndexer&)’:
test.h: error: ‘NonAssignable::NonAssignable(const NonAssignable&)’ is private

मैं इसके लिए हर कंपाइलर में काम करने के लिए बहुत निश्चित नहीं हूं, हालांकि। एक संबंधित प्रश्न है , लेकिन अभी तक कोई जवाब नहीं है।

युपीडी:

C ++ 11 में आप NonAssignableनिम्नानुसार कक्षा भी लिख सकते हैं :

class NonAssignable {
public:
    NonAssignable(NonAssignable const&) = delete;
    NonAssignable& operator=(NonAssignable const&) = delete;
    NonAssignable() {}
};

deleteतैयार किए गए कीवर्ड रोकता सदस्यों डिफ़ॉल्ट-निर्माण किया जा रहा है, ताकि वे एक व्युत्पन्न वर्ग के डिफ़ॉल्ट-निर्माण के सदस्यों में आगे नहीं किया जा सकता। असाइन करने का प्रयास GCC में निम्नलिखित त्रुटि देता है:

test.cpp: error: use of deleted function
          ‘SymbolIndexer& SymbolIndexer::operator=(const SymbolIndexer&)’
test.cpp: note: ‘SymbolIndexer& SymbolIndexer::operator=(const SymbolIndexer&)’
          is implicitly deleted because the default definition would
          be ill-formed:

युपीडी:

बूस्ट में पहले से ही एक ही उद्देश्य के लिए एक वर्ग है, मुझे लगता है कि यह इसी तरह से लागू किया गया है। कक्षा को बुलाया जाता है boost::noncopyableऔर इसका उपयोग निम्नलिखित के रूप में किया जाता है:

#include <boost/core/noncopyable.hpp>

class SymbolIndexer: public Indexer, private boost::noncopyable {
};

अगर आपकी परियोजना नीति इसकी अनुमति देती है तो मैं बूस्ट के समाधान पर ध्यान देने की सलाह दूंगा। अधिक जानकारी boost::noncopyableके लिए एक और संबंधित प्रश्न भी देखें ।


नहीं होना चाहिए NonAssignable(const NonAssignable &other);?
ट्रॉयसेफ

मुझे लगता है कि यदि C ++ 11 deleteकीवर्ड सिंटैक्स में अपडेट किया जाता तो इस प्रश्न को और अधिक बढ़ावा मिलता ।
टॉम ज़ातो -

@ TomášZato: विचार यह है कि कॉपी कंस्ट्रक्टर और असाइनमेंट ऑपरेटर को उपस्थित रखा जाए, लेकिन निजी। यदि आप deleteउन्हें, यह काम करना बंद कर देता है (मैंने अभी जाँच की है)।
फायरगुरफिकु

@ TomášZato: आह, क्षमा करें, मेरा परीक्षण तरीका थोड़ा गलत था। कामों को हटाना भी। एक मिनट में जवाब अपडेट कर देगा।
फायरगुरफिकु

3
@ ट्रॉयसेफ: const Class&और Class const&बहुत समान हैं। संकेत के लिए आप Class const * constटाइप भी कर सकते हैं ।
अग्निगुरिकु

4

SymbolIndexer( const SymbolIndexer& )निजी बनाओ । यदि आप एक संदर्भ दे रहे हैं, तो आप प्रतिलिपि नहीं बना रहे हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.