2013-03-04 17 views
7
#include <iostream> 
using namespace std; 

class Foo{ 

     string _s; 
     public: 
     Foo(string ss){ 
       _s = ss; 
     } 
     Foo& operator=(bool b){ 
       cout << "bool" << endl; 
       return *this; 
     } 
     Foo& operator=(const string& ss){ 
       cout << "another one" << endl; 
       return *this; 
     } 
}; 


int main(){ 

     Foo f("bar"); 
     f = "this"; 
     return 0; 

} 

मैंने = ऑपरेटर अधिभारित किया है। operator=(const string& ss) ओवरलोड पर कॉल करने के लिए मुझे f = "this"; कथन की उम्मीद थी। लेकिन ऐसा नहीं है। यह operator=(bool b) ओवरलोड पर कॉल करता है। क्यूं कर?अजीब ऑपरेटर अधिभार व्यवहार?

उत्तर

13

इस ऑपरेटर operator=(const string& ss) जबकि bool संस्करण से कोई भी है और इसलिए एक बेहतर मैच प्रदान करता है, तर्क (std::string-const char*) के लिए एक उपयोगकर्ता परिभाषित प्रकार के रूपांतरण की आवश्यकता है: आप के लिए const char* से निर्मित प्रकार const char[5] रूपांतरण प्राप्त bool

+0

क्या? उस अधिभार में केवल एक यूडीटी है। (इसके अलावा, 100% सही) –

+0

@MooingDuck हाँ, आप सही हैं। जब मैंने बिना सोच के जवाब टाइप किया तो यह समझ में आया! – juanchopanza

+1

+1: यह भाषा में नए आने वालों को आश्चर्यचकित कर सकता है कि मानक द्वारा परिभाषित एक प्रकार को ** उपयोगकर्ता ** - परिभाषित प्रकार के रूप में वर्गीकृत किया जाएगा, लेकिन वहां आप जाते हैं! – Johnsyweb

0

सी ++ मानकों में डील किए बिना, आपकी समस्या यह है कि आपने स्ट्रिंग & और एक बूल के साथ अपना असाइनमेंट अधिभार परिभाषित किया है लेकिन आपके परीक्षण में आप char * array निर्दिष्ट कर रहे हैं।

तो यदि आप एक स्ट्रिंग को परिभाषित करते हैं और असाइन करते हैं, तो यह अपेक्षित काम करेगा।

यहाँ काम यह जाँच करें: http://codepad.org/owb6noXR

+1

एक वैकल्पिक समाधान जो कॉलर से ज़िम्मेदारी को हटाता है, यहां है: http://liveworkspace.org/code/6UxaG$1 लेकिन यह वास्तव में *** *** के प्रश्न का उत्तर नहीं देता है कि विशेष ओवरलोड का आह्वान किया जाता है। – Johnsyweb

0

के रूप में अन्य लोगों ने कहा, इस के लिए एक आसान ठीक बस एक std::string करने के लिए अपने स्ट्रिंग कास्ट करने के लिए है, जब ऑपरेटर कर रही है, तो सी ++ वास्तव में जानता है कि किसे चुनना है ओवरलोड:

#include <iostream> 
using namespace std; 

class Foo{ 

     string _s; 
     public: 
     Foo(string ss){ 
       _s = ss; 
     } 
     Foo& operator=(bool b){ 
       cout << "bool" << endl; 
       return *this; 
     } 
     Foo& operator=(const string& ss){ 
       cout << "another one" << endl; 
       return *this; 
     } 
}; 


int main(){ 

     Foo f((string)"bar"); 
     f = (string)"this"; 
     return 0; 

} 
+1

जैसा कि मैंने किसी अन्य उत्तर पर टिप्पणी की, एक वैकल्पिक समाधान जो कॉलर से ज़िम्मेदारी को हटाता है [यहां] (http://liveworkspace.org/code/6UxaG$1) लेकिन यह वास्तव में *** के सवाल का जवाब नहीं देता है *** कि विशेष अधिभार लागू किया जाता है। – Johnsyweb

1

एक और उत्तर से बताया गया है, bool रूपांतरण के लिए सूचक करने वाली चार पसंद किया जाता है क्योंकि इसमें कोई उपयोगकर्ता-निर्धारित रूपांतरण शामिल है, जबकि std::string रूपांतरण उस में एक उपयोगकर्ता-निर्धारित रूपांतरण है।

सी ++ 11 मैन्युअल प्रकार नियंत्रण करने की क्षमता प्रदान करता है।

template<size_t n> 
struct enumarated_enum { 
private: 
    enum empty {}; 
}; 

template<bool b, size_t n=0> 
using EnableIf = typename std::enable_if< b, typename enumerated_enum<n>::empty >::type; 

template<typename String, EnableIf< std::is_convertible< String, std::string >::value >... > 
Foo& operator=(String&& s) { 
    cout << "string overload" << "\n"; 
} 

// either this: 
template<typename Bool, EnableIf< !std::is_convertible< Bool, std::string >::value && std::is_convertible< Bool, bool >::value, 1 >... > 
Foo& operator=(Bool&& b) { 
    cout << "bool overload" << "\n"; 
} 
// or this: 
Foo& operator=(bool b) { 
    cout << "bool overload" << "\n"; 
} 

जहाँ हम पूरी तरह से एक प्रकार से मेल खाते हैं अगर यह एक std::string में बदला जा सकता है, और टेम्पलेट से मेल नहीं खाता है, तो यह std::string में परिवर्तित नहीं किया जा सकता है और अन्य भार के को देखा जाता है।

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

(दूसरा टेम्पलेट तर्क गिने enum रों की एक variardic सूची जो मौजूद नहीं कर सकते, जिसका एकमात्र उद्देश्य यह सुनिश्चित करना है कि दो टेम्पलेट्स संकलक के लिए पर्याप्त तरीकों से भिन्न नहीं हैं।)

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