2012-04-23 19 views
10

संपादित करें: माइक सेमुर की टिप्पणी के बाद, मैंने को operator char *() const; के साथ बदल दिया और तदनुसार कार्यान्वयन को बदल दिया। यह अंतर्निहित कास्टिंग की अनुमति देता है, लेकिन, किसी कारण से, हस्ताक्षर किए गए लंबे int ऑपरेटर को char * ऑपरेटर पर प्राथमिकता है, जो कि सही नहीं लगता ... इसके अलावा, मैं अजीब सी सामान जैसे char * के बाहर खुलासा नहीं करना चाहता कक्षा, जब मेरे पास std :: स्ट्रिंग है। मेरे पास एक झुकाव है कि मेरी इच्छित फीचर को समर्थन देने के लिए मेरी कस्टमाइज्डइन्ट क्लास को कुछ सामानों से प्राप्त करने की आवश्यकता है। क्या कोई std::basic_string के बारे में माइक की टिप्पणी विस्तृत कर सकता है? मुझे यकीन नहीं है कि मैं इसे ठीक से समझ गया।सी ++ लागू रूपांतरण ऑपरेटर प्राथमिकता

#include <string> 
#include <sstream> 
#include <iostream> 

class CustomizedInt 
{ 
private: 
    int data; 
public: 
    CustomizedInt() : data(123) 
    { 
    } 
    operator unsigned long int() const; 
    operator std::string() const; 
}; 

CustomizedInt::operator unsigned long int() const 
{ 
    std::cout << "Called operator unsigned long int; "; 
    unsigned long int output; 
    output = (unsigned long int)data; 
    return output; 
} 

CustomizedInt::operator std::string() const 
{ 
    std::cout << "Called operator std::string; "; 
    std::stringstream ss; 
    ss << this->data; 
    return ss.str(); 
} 

int main() 
{ 
    CustomizedInt x; 
    std::cout << x << std::endl; 
    return 0; 
} 

कौन सा प्रिंट ", 123 कहा जाता है ऑपरेटर अहस्ताक्षरित लंबे int":


मैं कोड के इस टुकड़े की है। मेरे प्रश्न ये हैं:

  1. ऑपरेटर को हस्ताक्षरित लंबे int को हटाने के बाद, मुझे एक्स को std :: स्ट्रिंग को स्पष्ट रूप से क्यों डालना होगा? यह अंतर्निहित कास्ट ऑपरेटर (std :: string) को सीधे क्यों नहीं बुलाता है?
  2. क्या कोई दस्तावेज है जो बताता है कि कौन से निहित जानवरों की अनुमति है और उनका प्राथमिकता क्या है? ऐसा लगता है कि अगर मैं ऑपरेटर को बिना हस्ताक्षर किए गए लंबे int int के साथ एक ऑपरेटर हस्ताक्षरित int जोड़ता हूं, तो मुझे < < ऑपरेटर के लिए अस्पष्टता के बारे में एक कंपाइलर त्रुटि प्राप्त होती है ...
  3. इसके अलावा, मुझे पता है कि ऐसे ऑपरेटर को परिभाषित किया जा सकता है खराब अभ्यास, लेकिन मुझे यकीन नहीं है कि मैं संबंधित चेतावनी को पूरी तरह से समझता हूं। क्या कोई उन्हें रेखांकित कर सकता है? सार्वजनिक तरीकों को परिभाषित करने के लिए बेहतर अभ्यास करना होगा ToUnsignedLongInt और ToString?
+0

यह संबंधित है: [स्ट्रिंग में अंतर्निहित रूपांतरण के माध्यम से ऑब्जेक्ट स्ट्रीम करते समय ओवरलोड रिज़ॉल्यूशन विफलता] (http://stackoverflow.com/questions/6677072/overload-resolution-failure-when-streaming-object-via-implicit-conversion -to-str) –

+0

@Als: चलिए इसे धीरे-धीरे लेते हैं ... मैं अभी तक टेम्पलेट्स में गोता लगाने के लिए तैयार नहीं हूं :) –

उत्तर

8

बाद मैं ऑपरेटर अहस्ताक्षरित लंबे int निकालने के लिए, कारण है कि मैं एक्स कास्ट करने के लिए एसटीडी :: स्ट्रिंग स्पष्ट रूप से की जरूरत है? यह अंतर्निहित कास्ट ऑपरेटर (std :: string) को सीधे क्यों नहीं बुलाता है?

स्ट्रिंग्स के लिए << के संस्करण एक टेम्पलेट, std::basic_string टेम्पलेट के मापदंडों से parametrised (std::string ही है कि टेम्पलेट की एक विशेषज्ञता जा रहा है) है। इसे केवल तर्क-निर्भर लुकअप द्वारा चुना जा सकता है, और यह केवल तभी काम करता है जब तर्क वास्तव में std::basic_string का विशेषज्ञता है, उसमें कुछ परिवर्तनीय नहीं है।

क्या कोई दस्तावेज है जो बताता है कि कौन से निहित जानवरों की अनुमति है और उनका प्राथमिकता क्या है?

नियम काफी जटिल हैं, और आपको पूरी कहानी के लिए सी ++ मानक पढ़ने की आवश्यकता होगी। अंगूठे के सरल नियम यह हैं कि निहित रूपांतरणों में एक से अधिक उपयोगकर्ता परिभाषित रूपांतरण नहीं हो सकते हैं और (जैसा कि आपने पाया है) एक अंतर्निहित रूपांतरण का परिणाम तर्क-निर्भर लुकअप द्वारा टेम्पलेट विशेषज्ञता चुनने के लिए उपयोग नहीं किया जा सकता है।

मुझे यकीन नहीं है कि मैं संबंधित चेतावनी पूरी तरह से समझता हूं। क्या कोई उन्हें रेखांकित कर सकता है?

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

क्या सार्वजनिक तरीकों को परिभाषित करने के लिए बेहतर अभ्यास करना होगा ToUnsignedLongInt और ToString?

अवांछित रूपांतरणों से बचने के लिए शायद यह एक अच्छा विचार है। आप उन्हें छोड़ कर अपनी समस्या के समाधान के लिए और उन्हें स्पष्ट रूप से उपयोग करें जब आवश्यक कर सकते हैं:

std::cout << std::string(x) << std::endl; 

सी ++ 11 में, आप उन्हें explicit, घोषणा कर सकते हैं ताकि वे केवल इस तरह से इस्तेमाल किया जा सकता। मेरी राय में, यदि आप कर सकते हैं तो यह सबसे अच्छा विकल्प होगा; अन्यथा, जैसा कि आप सुझाव देते हैं, मैं स्पष्ट रूपांतरण कार्यों का उपयोग करूंगा।

वैसे, main() का रिटर्न प्रकार int होना चाहिए, void नहीं।

+0

माइक: इस तरह की एक विस्तृत टिप्पणी प्रदान करने के लिए समय निकालने के लिए धन्यवाद। यह चीजों को थोड़ा सा साफ़ करता है। इसके अलावा, "शून्य मुख्य" के साथ उस छोटे मुद्दे को खोजने के लिए धन्यवाद। मुझे सही संस्करण का उपयोग करना याद रखना चाहिए, इससे कोई फर्क नहीं पड़ता :) –