दिलचस्प पोस्ट
सफारी के साथ html5 स्थानीय स्टॉरेज त्रुटि: "QUOTA_EXCEEDED_ERR: DOM अपवाद 22: कोटा को पार करने वाले स्टोरेज में कुछ जोड़ने के लिए एक प्रयास किया गया था।" मैं टिक्स को डेट प्रारूप में कैसे रूपांतरित कर सकता / सकती हूं? क्या पायथन में एक स्ट्रिंग 'शामिल' सबस्ट्रिंग पद्धति है? यूटीएफ -8, यूटीएफ -16, और यूटीएफ -32 जावास्क्रिप्ट ECMAScript 6 में स्ट्रिंग से वस्तु बनाएं शून्य भरा जावास्क्रिप्ट एरे बनाने के लिए सबसे कारगर तरीका है? यदि वैरिएबल नाम स्ट्रिंग के रूप में संग्रहीत है तो एक वैरिएबल वैल्यू कैसे प्राप्त करें? जावा – एक ही वर्ग के विभिन्न संस्करणों को कैसे लोड करें? ग्रहण में एक गीथहब प्रोजेक्ट आयात करना स्प्रिंग बूट स्थिर सामग्री की सेवा नहीं दे रहा है किसी दूसरे निर्माता से कॉल करें पायथन में निश्चित चौड़ाई में एक अस्थायी संख्या को कैसे प्रारूपित करें क्यूटी के पीआईएमपीएल मुहावरों का उपयोग कैसे करें? कैसे टॉमकेट पर सीडीआई स्थापित और उपयोग करें? पीआईएल में परिप्रेक्ष्य परिवर्तन कैसे काम करता है?

क्लास पदानुक्रम के लिए ओवरलोड ऑपरेटर == का सही तरीका क्या है?

मान लीजिए मेरे पास निम्न श्रेणी के पदानुक्रम हैं:

class A { int foo; virtual ~A() = 0; }; A::~A() {} class B : public A { int bar; }; class C : public A { int baz; }; 

इन वर्गों के लिए ओवरलोड operator== का सही तरीका क्या है? अगर मैं उन्हें सभी निशुल्क कार्य करता है, तो बी और सी का कास्टिंग बिना ए के संस्करण का लाभ उठा सकता है। यह किसी को ए के संदर्भ में गहरी तुलना करने से भी रोका जा सकता है। अगर मैं उन्हें वर्चुअल सदस्य कार्य बना देता हूं, तो एक व्युत्पन्न संस्करण ऐसा दिखाई दे सकता है:

 bool B::operator==(const A& rhs) const { const B* ptr = dynamic_cast<const B*>(&rhs); if (ptr != 0) { return (bar == ptr->bar) && (A::operator==(*this, rhs)); } else { return false; } } 

फिर से, मुझे अभी भी डालना है (और यह गलत लगता है) ऐसा करने का कोई पसंदीदा तरीका है?

अद्यतन करें:

अभी तक केवल दो उत्तर दिए गए हैं, लेकिन यह सही तरीके से असाइनमेंट ऑपरेटर के समान दिखता है:

  • गैर-पत्ती कक्षाएं सार करें
  • गैर-पान कक्षाओं में संरक्षित गैर-आभासी
  • पब्लिक क्लास में सार्वजनिक गैर-वर्चुअल

किसी भी उपयोगकर्ता को विभिन्न प्रकार की दो वस्तुओं की तुलना करने का प्रयास नहीं किया जाएगा, क्योंकि आधार फ़ंक्शन सुरक्षित है, और पत्ती वर्ग डेटा के उस हिस्से की तुलना करने के लिए माता-पिता के संस्करण का लाभ उठा सकते हैं।

Solutions Collecting From Web of "क्लास पदानुक्रम के लिए ओवरलोड ऑपरेटर == का सही तरीका क्या है?"

मैं एक ही समस्या दूसरे दिन कर रहा था और मैं निम्नलिखित समाधान के साथ आया था:

 struct A { int foo; A(int prop) : foo(prop) {} virtual ~A() {} virtual bool operator==(const A& other) const { if (typeid(*this) != typeid(other)) return false; return foo == other.foo; } }; struct B : A { int bar; B(int prop) : A(1), bar(prop) {} bool operator==(const A& other) const { if (!A::operator==(other)) return false; return bar == static_cast<const B&>(other).bar; } }; struct C : A { int baz; C(int prop) : A(1), baz(prop) {} bool operator==(const A& other) const { if (!A::operator==(other)) return false; return baz == static_cast<const C&>(other).baz; } }; 

इस बात को मैं इस बारे में पसंद नहीं करता टाइपिड चेक है I आपने इस बारे में क्या सोचा?

इस प्रकार के पदानुक्रम के लिए मैं निश्चित रूप से स्कॉट मेयर की प्रभावी सी ++ सलाह का पालन करेंगे और कोई भी ठोस बेस क्लास होने से बचें। आप किसी भी मामले में ऐसा कर रहे हैं।

मैं operator== को एक नि: शुल्क कार्य के रूप में कार्यान्वित करूंगा, शायद दोस्तों, केवल ठोस पत्ती-नोड वर्ग के प्रकार के लिए।

यदि बेस क्लास के पास डेटा सदस्यों की ज़रूरत होती है, तो मैं बेस क्लास में एक (शायद सुरक्षित) गैर-वर्चुअल सहायक फ़ंक्शन प्रदान कर सकता isEqual (है, isEqual , कहते हैं) जो व्युत्पन्न क्लासेस operator== उपयोग कर सकते हैं।

उदाहरण के लिए

 bool operator==(const B& lhs, const B& rhs) { lhs.isEqual( rhs ) && lhs.bar == rhs.bar; } 

operator== टालने से, जो बुनियादी आधार वर्गों पर काम करता है और संरक्षित कार्यों की तुलना करना रखता है, आपको क्लाइंट कोड में गलती से गड़बड़ी नहीं मिलती है, जहां दो अलग-अलग प्रकार की टाइप ऑब्जेक्ट्स का आधार भाग की तुलना की जाती है।

मुझे यकीन नहीं है कि क्या मैं एक dynamic_cast साथ एक आभासी तुलना समारोह को लागू करता हूं, मैं ऐसा करने से अनिच्छुक हूं, लेकिन अगर इसके लिए एक सिद्ध आवश्यकता होती है तो मैं शायद बेस क्लास में एक शुद्ध आभासी फ़ंक्शन ( नहीं operator== ) जो तब कंक्रीट व्युत्पन्न कक्षाओं में ओवरराइड किया गया था, इस तरह से ऐसा कुछ, operator== का उपयोग करके व्युत्पन्न वर्ग के लिए।

 bool B::pubIsEqual( const A& rhs ) const { const B* b = dynamic_cast< const B* >( &rhs ); return b != NULL && *this == *b; } 

यदि आप उचित धारणा करते हैं कि दोनों वस्तुओं के प्रकार उनके समान होने के लिए समान हैं, तो प्रत्येक व्युत्पन्न वर्ग में आवश्यक बॉयलर-प्लेट की मात्रा को कम करने का एक तरीका है। यह आभासी तरीके को संरक्षित और सार्वजनिक इंटरफ़ेस के पीछे छिपाने के लिए हर्ब सटर की सिफारिशों का पालन ​​करता है। आनुवंशिक रूप से आवर्ती टेम्पलेट पैटर्न (सीआरटीपी) का प्रयोग बॉयलरप्लेट कोड को equals विधि में लागू करने के लिए किया जाता है ताकि व्युत्पन्न कक्षाओं की आवश्यकता न हो।

 class A { public: bool operator==(const A& a) const { return equals(a); } protected: virtual bool equals(const A& a) const = 0; }; template<class T> class A_ : public A { protected: virtual bool equals(const A& a) const { const T* other = dynamic_cast<const T*>(&a); return other != nullptr && static_cast<const T&>(*this) == *other; } private: bool operator==(const A_& a) const // force derived classes to implement their own operator== { return false; } }; class B : public A_<B> { public: B(int i) : id(i) {} bool operator==(const B& other) const { return id == other.id; } private: int id; }; class C : public A_<C> { public: C(int i) : identity(i) {} bool operator==(const C& other) const { return identity == other.identity; } private: int identity; }; 

http://ideone.com/SymduV पर एक डेमो देखें

यदि आप कास्टिंग का उपयोग नहीं करना चाहते हैं और यह भी सुनिश्चित कर लें कि दुर्घटना से आप सी के उदाहरण की तुलना में बी की तुलना नहीं करेंगे तो आपको स्कॉट मैयर्स की अधिक से अधिक प्रभावी सी ++ के आइटम 33 में सुझाए गए तरीके से अपने क्लास पदानुक्रम का पुनर्गठन करने की आवश्यकता होगी। असल में यह मद असाइनमेंट ऑपरेटर से संबंधित होता है, जो वास्तव में गैर-संबंधित प्रकारों के लिए उपयोग किए जाने पर कोई मतलब नहीं है। तुलना की प्रक्रिया के मामले में बी के उदाहरण सी की तुलना करते समय गलत तरीके से वापसी करने का मतलब होता है।

नीचे नमूना कोड है जो आरटीटीआई का उपयोग करता है, और वर्ग के पदानुक्रम को कंकरीट लीड्स और सार बेस में विभाजित नहीं करता है।

इस नमूना कोड के बारे में अच्छी बात यह है कि गैर-संबंधित उदाहरणों की तुलना करते समय आपको std :: bad_cast नहीं मिलेगा (जैसे बी के साथ सी)। फिर भी, कंपाइलर आपको ऐसा करने की अनुमति देगा जो वांछित हो सकता है, आप एक ही तरीके से ऑपरेटर में लागू कर सकते हैं <और विभिन्न ए, बी और सी इंस्टेंसेस के सदिश को सॉर्ट करने के लिए इसका इस्तेमाल कर सकते हैं।

जीना

 #include <iostream> #include <string> #include <typeinfo> #include <vector> #include <cassert> class A { int val1; public: A(int v) : val1(v) {} protected: friend bool operator==(const A&, const A&); virtual bool isEqual(const A& obj) const { return obj.val1 == val1; } }; bool operator==(const A& lhs, const A& rhs) { return typeid(lhs) == typeid(rhs) // Allow compare only instances of the same dynamic type && lhs.isEqual(rhs); // If types are the same then do the comparision. } class B : public A { int val2; public: B(int v) : A(v), val2(v) {} B(int v, int v2) : A(v2), val2(v) {} protected: virtual bool isEqual(const A& obj) const override { auto v = dynamic_cast<const B&>(obj); // will never throw as isEqual is called only when // (typeid(lhs) == typeid(rhs)) is true. return A::isEqual(v) && v.val2 == val2; } }; class C : public A { int val3; public: C(int v) : A(v), val3(v) {} protected: virtual bool isEqual(const A& obj) const override { auto v = dynamic_cast<const C&>(obj); return A::isEqual(v) && v.val3 == val3; } }; int main() { // Some examples for equality testing A* p1 = new B(10); A* p2 = new B(10); assert(*p1 == *p2); A* p3 = new B(10, 11); assert(!(*p1 == *p3)); A* p4 = new B(11); assert(!(*p1 == *p4)); A* p5 = new C(11); assert(!(*p4 == *p5)); } 
  1. मुझे लगता है कि यह अजीब लग रहा है:

     void foo(const MyClass& lhs, const MyClass& rhs) { if (lhs == rhs) { MyClass tmp = rhs; // is tmp == rhs true? } } 
  2. अगर ऑपरेटर को कार्यान्वित करना == एक कानूनी प्रश्न की तरह लगता है, तो प्रकार के विलोपन पर विचार करें (वैसे भी मिटाए जाने के तरीके पर विचार करें, यह एक सुंदर तकनीक है)। यहां शॉन पेरेंट का वर्णन किया गया है। फिर आपको कुछ बहु-प्रेषण करना होगा यह एक अप्रिय समस्या है यहाँ इसके बारे में एक बात है

  3. पदानुक्रम के बजाय वेरिएंट का उपयोग करने पर विचार करें वे आसानी से इस प्रकार की चीजों को आसानी से कर सकते हैं