2015-01-29 9 views
5

पर विचार करें:उलझाव से बुला प्रतिलिपि निर्माता

struct Foo 
{ 
    Foo(std::string str) {} 
}; 

struct Bar 
{ 
    Bar(Foo f) {} 
}; 

int main(int argc, char* argv[]) 
{ 
    Foo f("test"); 

    Bar b1(f); 
    Bar b2(std::string("test")); 
    Bar b3("test"); 

    return 0; 
} 

यह बी 3 की घोषणा पर संकलित करने के लिए विफल रहता है ([5] स्थिरांक चार फू '' 'को' 'से तर्क 1 परिवर्तित नहीं कर सकते')। जो समझ में आता है, क्योंकि कॉन्स्ट चार को फू में परिवर्तित करने का कोई सीधा तरीका नहीं है। हालांकि, कॉन्स्ट char को std :: स्ट्रिंग में कनवर्ट करने का एक तरीका है, और उसके बाद फ़ू बनाने के लिए इसका उपयोग करें (जो बी 1 और बी 2 में हो रहा है), और यही वह है जो मैं चाहता हूं क्योंकि यह API nicer बनाता है उपयोग करने के लिए (एक फू या std :: स्ट्रिंग को तुरंत हर बार चालू करने के लिए नहीं)।

तो मेरा सवाल यह है: क्या कंपाइलर को फू (std :: string) प्रतिलिपि कन्स्ट्रक्टर को निहित रूप से कॉल करने का कोई तरीका है? दूसरे शब्दों में, क्या बी 3 काम की तरह घोषणा करने का कोई तरीका है, इसे बी 2 के समान होना चाहिए, और फू के लिए एक कॉन्स char * कॉपी कन्स्ट्रक्टर घोषित किए बिना? (आखिरी बात यह स्पष्ट तरीका है, लेकिन मेरा वास्तविक कोड निश्चित रूप से उतना आसान नहीं है, और मैं कॉन्स char * प्रतिलिपि बनाने वालों को जोड़ने और कन्स्ट्रक्टर में अन्य सभी प्रारंभिकरणों को सही तरीके से संभालने और इसे ध्यान में रखते हुए पसंद नहीं करना चाहता std :: स्ट्रिंग कॉपी कन्स्ट्रक्टर के साथ सिंक करें)।

+6

एक निहित रूपांतरण अनुक्रम में केवल एक उपयोगकर्ता परिभाषित रूपांतरण शामिल होने की अनुमति है। आप दो ('const char *' से 'std :: string', फिर' std :: string' को 'foo'' के लिए पूछ रहे हैं। जाने का एक तरीका 'फू' कन्स्ट्रक्टर ओवरलोड को 'कॉन्स चार *' लेना होगा। –

+0

नाइटपिक: आपके द्वारा उल्लेख किए जाने वाले रचनाकारों में से कोई भी * प्रति * कन्स्ट्रक्टर नहीं है, वे केवल निर्माता हैं। – molbdnilo

+0

धन्यवाद, 'निहित रूपांतरण अनुक्रम' वह जादू स्ट्रिंग है जिसे मैं ढूंढ रहा था। वास्तव में जो करना चाहता था वह करना असंभव है, मुझे एक अतिरिक्त कन्स्ट्रक्टर का उपयोग करना होगा। – Roel

उत्तर

1

क्या यह बदलने के बारे में:

struct Bar 
{ 
    Bar(Foo f) {} 
}; 

struct Bar 
{ 
    Bar(Foo f) {} 
    Bar(std::string f) {} 
}; 

बहुरूपता का उपयोग कर ... को

+5

पॉलिमॉर्फिज्म (ओओपी की सामान्य समझ में) के साथ इसका कोई संबंध नहीं है, यह बस ओवरलोडिंग है। – Puppy

+0

धन्यवाद, लेकिन यह एक ही रखरखाव के मुद्दों से पीड़ित है (मेरे मामले में) मैं कॉन्स्ट char * कन्स्ट्रक्टर नहीं होने से बचने की कोशिश कर रहा था। ऐसा लगता है कि मुझे यह काम करने के लिए एक अतिरिक्त कन्स्ट्रक्टर बनाना होगा। – Roel

8

C++ 11 स्वीकार्य है, आप Foo करने के लिए एक सौंपने के निर्माता जोड़ सकते हैं जो const char* लेता है और बस अन्य कन्स्ट्रक्टर को कॉल करता है:

struct Foo 
{ 
    Foo(std::string str) {} 
    Foo(const char* str) : Foo(std::string(str)) {} 
}; 

वैकल्पिक रूप से, आप C++ 14 के इस्तेमाल कर सकते हैं std::string शाब्दिक:

struct Foo 
{ 
    Foo(std::string str) { init(str); } 
    Foo(const char* str) { init(str); } 
    void init(std::string str) {} 
}; 

का नकारात्मक पहलू:

using namespace::std::string_literals; 
Bar b3("test"s); 

तुम भी एक सौंपने के निर्माता दोनों कंस्ट्रक्टर्स एक अलग समारोह फोन होने से अनुकरण कर सकता है उपरोक्त यह है कि आपको प्रारंभिक सूचियों में जो कुछ भी कर रहे थे, उसके बारे में सावधानी से सोचने की आवश्यकता होगी जिसे अब आपको init के शरीर में करने की आवश्यकता है।

+0

वीएस2013, कोई प्रतिनिधि कन्स्ट्रक्टर नहीं और न ही std :: स्ट्रिंग शाब्दिक :( – Roel

+0

@Roel मेरे संपादन में प्रतिनिधि रचनाकारों को अनुकरण करने के बारे में कैसे? – TartanLlama

+1

हाँ, मैं यही कर रहा हूं जो मुझे लगता है।नुकसान (जैसा कि मुझे यकीन है कि आप जानते हैं) यह है कि सदस्यों को जगह में नहीं बनाया जाएगा। जो गति के संदर्भ में मेरे कोड में बिल्कुल ध्यान देने योग्य या मापनीय नहीं होगा, लेकिन यह अभी भी थोड़ा सा लगता है;) – Roel

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