दिलचस्प पोस्ट
जावा थ्रेड उदाहरण? Android java.net.UnknownHostException: होस्ट अनसुलझे है (रणनीति प्रश्न) क्या SPARQL में आरडीएफ संग्रह में एक तत्व की स्थिति प्राप्त करना संभव है? एक जार में पैकेजिंग फेसलेट फ़ाइलें (टेम्पलेट्स, शामिल हैं, कंपोजिट) jQuery प्लगइन टेम्पलेट – सर्वोत्तम अभ्यास, सम्मेलन, प्रदर्शन और स्मृति प्रभाव जावा एक्सएमएल लाइब्रेरी क्या है (dom4j को बदलने के लिए)? Angular2 के साथ फ़ाइल अपलोड करने के लिए बाकी एपीआई फ़ायरफ़ॉक्स में अचानक क्यों "अवरूद्ध मिश्रित सक्रिय सामग्री" समस्या हो रही है? बैच फ़ाइल में वेरिएबल के रूप में कमांड आउटपुट कैसे सेट करें gulp कमांड नहीं मिला – गुल स्थापित करने के बाद त्रुटि हमेशा पृष्ठभूमि में एक सेवा कैसे चलाने के लिए? चेतावनी: mysqli_query () पैरामीटर 1 को mysqli होने की उम्मीद है, शून्य में दिए गए EXC_BAD_ACCESS संकेत मिला अस्पष्ट पारदर्शी पृष्ठभूमि प्रभाव बनाएँ पद्धति को किसी स्टोर की अभिव्यक्ति में अनुवाद नहीं किया जा सकता

सी ++ में बेस क्लास के कंस्ट्रक्टर और असाइनमेंट ऑपरेटर का उपयोग कैसे करें?

मेरे पास कक्षा बी का निर्माणकर्ताओं और एक असाइनमेंट ऑपरेटर है।

class B { public: B(); B(const string & s); B(const B & b){(*this) = b;}; B & operator= (const B & b); private: virtual void foo(); // and other private member variables and functions } 

मैं एक विरासत वर्ग डी बनाना चाहता हूँ जो कि फ़ंक्शन फ़ू () को ओवरराइड करेगा, और कोई अन्य परिवर्तन आवश्यक नहीं है।

लेकिन मैं डी को कन्स्ट्रक्टरों का एक ही सेट रखना चाहता हूं, जिसमें कॉपी कन्स्ट्रक्टर और असाइनमेंट ऑपरेटर बी के रूप में शामिल है:

  D(const D & d){(*this) = d;}; D & operator= (const D & d); 

क्या मुझे डी में उन सभी को फिर से लिखना है, या क्या बी के कंस्ट्रक्टर और ऑपरेटर का उपयोग करने का कोई तरीका है? मैं विशेष रूप से असाइनमेंट ऑपरेटर को फिर से लिखना नहीं चाहूंगा क्योंकि उसे बी के सभी निजी सदस्य चर का उपयोग करना होगा।

वेब के समाधान से एकत्रित समाधान "सी ++ में बेस क्लास के कंस्ट्रक्टर और असाइनमेंट ऑपरेटर का उपयोग कैसे करें?"

आप स्पष्ट रूप से कन्स्ट्रक्टर और असाइनमेंट ऑपरेटर कॉल कर सकते हैं:

 class Base { //... public: Base(const Base&) { /*...*/ } Base& operator=(const Base&) { /*...*/ } }; class Derived : public Base { int additional_; public: Derived(const Derived& d) : Base(d) // dispatch to base copy constructor , additional_(d.additional_) { } Derived& operator=(const Derived& d) { Base::operator=(d); additional_ = d.additional_; return *this; } }; 

दिलचस्प बात ये है कि यह काम करता है भले ही आपने इन कार्यों को स्पष्ट रूप से परिभाषित नहीं किया हो (यह तब कंपाइलर द्वारा निर्मित फ़ंक्शन का उपयोग करता है)।

 class ImplicitBase { int value_; // No operator=() defined }; class Derived : public ImplicitBase { const char* name_; public: Derived& operator=(const Derived& d) { ImplicitBase::operator=(d); // Call compiler generated operator= name_ = strdup(d.name_); return *this; } }; 

लघु उत्तर: हाँ, आपको डी में कार्य दोहराने की आवश्यकता होगी

लंबा जवाब:

यदि आपके व्युत्पन्न वर्ग 'डी' में कोई नया सदस्य चर नहीं है, तो डिफ़ॉल्ट संस्करण (संकलक द्वारा जेनरेट किया जाना चाहिए सिर्फ ठीक काम करना चाहिए)। डिफ़ॉल्ट प्रतिलिपि कन्स्ट्रक्टर मूल कॉपी निर्माता को कॉल करेगा और मूल असाइनमेंट ऑपरेटर मूल अभिभाषण ऑपरेटर को कॉल करेगा।

लेकिन अगर आपकी कक्षा 'डी' में संसाधन हैं तो आपको कुछ काम करने की आवश्यकता होगी।

मैं अपनी कॉपी निर्माता थोड़ा अजीब खोजता हूं:

 B(const B& b){(*this) = b;} D(const D& d){(*this) = d;} 

आम तौर पर कन्स्ट्रक्टर श्रृंखला की प्रतिलिपि बनाई जाती है ताकि वे आधार ऊपर से प्रतिलिपि बनाई जा सकें। यहां क्योंकि आप असाइनमेंट ऑपरेटर को कॉल कर रहे हैं, प्रतिलिपि कन्स्ट्रक्टर को डिफॉल्ट कन्स्ट्रक्टर को कॉल करना चाहिए ताकि ऑब्जेक्ट को नीचे से नीचे तक प्रारंभ किया जा सके। फिर आप असाइनमेंट ऑपरेटर का उपयोग करके फिर से नीचे जाएं। यह बल्कि अकार्य लगता है।

अब अगर आप असाइनमेंट करते हैं तो आप नीचे से ऊपर (या ऊपर नीचे) की प्रतिलिपि बना रहे हैं, लेकिन आपके लिए ऐसा करना कठिन लगता है और एक मजबूत अपवाद गारंटी प्रदान करें यदि किसी भी बिंदु पर संसाधन प्रतिलिपि करने में असफल रहता है और आप अपवाद फेंक देते हैं तो वस्तु अनिश्चित स्थिति में होगी (जो कि बुरी चीज है)।

आम तौर पर मैंने देखा है कि यह दूसरी तरह से किया है।
असाइनमेंट ऑपरेटर को प्रतिलिपि कन्स्ट्रक्टर और स्वैप के रूप में परिभाषित किया गया है। इसका कारण यह मजबूत अपवाद गारंटी प्रदान करना आसान बनाता है। मुझे नहीं लगता है कि आप इस तरह से ऐसा करकर मजबूत गारंटी प्रदान कर पाएंगे (मैं गलत हो सकता है)।

 class X { // If your class has no resources then use the default version. // Dynamically allocated memory is a resource. // If any members have a constructor that throws then you will need to // write your owen version of these to make it exception safe. X(X const& copy) // Do most of the work here in the initializer list { /* Do some Work Here */} X& operator=(X const& copy) { X tmp(copy); // All resource all allocation happens here. // If this fails the copy will throw an exception // and 'this' object is unaffected by the exception. swap(tmp); return *this; } // swap is usually trivial to implement // and you should easily be able to provide the no-throw guarantee. void swap(X& s) throws() { /* Swap all members */ } }; 

यहां तक ​​कि अगर आप एक्स से एक कक्षा डी प्राप्त करते हैं तो यह इस पैटर्न को प्रभावित नहीं करता है।
बेशक आपको बेस क्लास में स्पष्ट कॉल करके काम का एक सा दोहराया जाना चाहिए, लेकिन यह अपेक्षाकृत तुच्छ है।

 class D: public X { // Note: // If D contains no members and only a new version of foo() // Then the default version of these will work fine. D(D const& copy) :X(copy) // Chain X's copy constructor // Do most of D's work here in the initializer list { /* More here */} D& operator=(D const& copy) { D tmp(copy); // All resource all allocation happens here. // If this fails the copy will throw an exception // and 'this' object is unaffected by the exception. swap(tmp); return *this; } // swap is usually trivial to implement // and you should easily be able to provide the no-throw guarantee. void swap(D& s) throws() { X::swap(s); // swap the base class members /* Swap all D members */ } }; 

आपके पास सबसे अधिक संभावना आपके डिजाइन में एक दोष है (संकेत: टुकड़ा करने की क्रिया , इकाई शब्दार्थ बनाम मूल्य शब्दार्थ ) एक बहुरूपृत पदानुक्रम से किसी वस्तु पर पूर्ण प्रतिलिपि / मूल्य शब्दार्थ रखने के लिए अक्सर एक आवश्यकता नहीं होती है। यदि आप इसे प्रदान करना चाहते हैं, तो उसे बाद में इसकी आवश्यकता हो सकती है, इसका मतलब है कि आपको इसके लिए कभी आवश्यकता नहीं होगी। इसके बजाय बेस क्लास को प्रतिलिपि बनाइये (उदाहरण के लिए बढ़ावा देने से noncopyable ::)

केवल सही समाधान जब ऐसी ज़रूरत वास्तव में प्रकट होती है, लिफाफा-पत्र मुहावरे , या सीन ऑरजेक्ट्स पर लेख से सीन पेरेंट और अलेक्जेंडर स्टेपानोव आईआईआरसी द्वारा दिए गए छोटे फ्रेमवर्क हैं। अन्य सभी समाधान आपको टुकड़ा करने की क्रिया के साथ परेशानी दे देंगे, और / या एलएसपी।

आपको उन सभी कन्स्ट्रक्टर को फिर से परिभाषित करना होगा जो डिफॉल्ट नहीं हैं या कॉन्ट्रैक्टर्स कॉपी नहीं कर सकते। आपको प्रतिलिपि कन्स्ट्रक्टर को फिर से परिभाषित करने की आवश्यकता नहीं है और न ही असाइनमेंट ऑपरेटर के रूप में कम्पाइलर द्वारा दिए गए अनुसार (मानक के अनुसार) सभी आधार के संस्करणों को कॉल करेगा:

 struct base { base() { std::cout << "base()" << std::endl; } base( base const & ) { std::cout << "base(base const &)" << std::endl; } base& operator=( base const & ) { std::cout << "base::=" << std::endl; } }; struct derived : public base { // compiler will generate: // derived() : base() {} // derived( derived const & d ) : base( d ) {} // derived& operator=( derived const & rhs ) { // base::operator=( rhs ); // return *this; // } }; int main() { derived d1; // will printout base() derived d2 = d1; // will printout base(base const &) d2 = d1; // will printout base::= } 

ध्यान दें, जैसा कि एसबीआई ने उल्लेख किया है, यदि आप किसी भी निर्माता को परिभाषित करते हैं तो कंपाइलर आपके लिए डिफ़ॉल्ट कन्स्ट्रक्टर नहीं बनाएगा और इसमें प्रतिलिपि कन्स्ट्रक्टर भी शामिल होगा।

मूल कोड गलत है:

 class B { public: B(const B& b){(*this) = b;} // copy constructor in function of the copy assignment B& operator= (const B& b); // copy assignment private: // private member variables and functions }; 

सामान्य तौर पर, आप प्रतिलिपि असाइनमेंट के संदर्भ में प्रतिलिपि कन्स्ट्रक्टर को परिभाषित नहीं कर सकते, क्योंकि प्रतिलिपि असाइनमेंट को संसाधन जारी करना होगा और प्रतिलिपि निर्माता नहीं है !!!

इसे समझने के लिए, इस पर विचार करें:

 class B { public: B(Other& ot) : ot_p(new Other(ot)) {} B(const B& b) {ot_p = new Other(*b.ot_p);} B& operator= (const B& b); private: Other* ot_p; }; 

स्मृति रिसाव से बचने के लिए, प्रतिलिपि असाइनमेंट पहले ही ot_p द्वारा इंगित की गई स्मृति को हटाना चाहिए:

 B::B& operator= (const B& b) { delete(ot_p); // <-- This line is the difference between copy constructor and assignment. ot_p = new Other(*b.ot_p); } void f(Other& ot, B& b) { B b1(ot); // Here b1 is constructed requesting memory with new b1 = b; // The internal memory used in b1.op_t MUST be deleted first !!! } 

इसलिए, प्रतिलिपि निर्माता और प्रतिलिपि असाइनमेंट अलग-अलग है क्योंकि एक पुराने मेमोरी में पूर्व निर्माण और ऑब्जेक्ट और, बाद में, जरूरी है कि मौजूदा ऑब्जेक्ट को नए ऑब्जेक्ट के निर्माण से पहले रिलीज़ करें।

यदि आप मूल रूप से इस आलेख में सुझाए गए हैं:

 B(const B& b){(*this) = b;} // copy constructor 

आप एक अप्रयुक्त स्मृति को हटा देंगे