2017-05-06 4 views
6

लेने कहते हैं कि हम, एक वर्ग है कि उत्पादनइंटरफेस डिजाइन: अतिभारित समारोह की सुरक्षा स्ट्रिंग और चार सरणी

class Writer 
{ 
public: 
    int write(const std::string& str); 
    int write(const char* str, int len); 
    //... 
}; 

मैं इस के साथ ठीक इसके लचीला था, के लिए सामग्री लिखते हैं और जो कुछ कर सकते हैं जब तक मैं

का एहसास
char* buf = new char[n]; //not terminated with '\0' 
//load up buf 
Writer w; 
w.write(buf); //compiles! 

यह वास्तव में गंदा बग है।

हम कुछ templating

class WriterV2 
{ 
public: 
    int write(const std::string& str); 
    int write(const char* str, int len); 
    template<typename... Args> 
    int write(const char*, Args...) 
    { static_assert(sizeof...(Args) < 0, "Incorrect arguments"); } 
    //... 
}; 

साथ कुछ हद तक संशोधन कर सकते हैं लेकिन इस विधि अपनी समस्याओं

WriterV2 w; 
w.write("The templating genius!"); //compile error 

मुझे क्या करना चाहिए है? एक बेहतर डिजाइन क्या है?

और किसी से पूछने से पहले, const char (&)[N]does not work के लिए ओवरलोडिंग। ऐसा करने के लिए एक रैपर बनाने के लिए संभव हो सकता है, लेकिन ऐसा लगता है ... overkill?

EDIT एक विधि write(char*) जोड़ने और एक त्रुटि उत्सर्जित आदर्श नहीं है। buf को फ़ंक्शंस के माध्यम से पास करते समय और यह सब const char* हो सकता है।

+1

क्यों आप इस मामले को संभालने के लिए एक विधि घोषित नहीं करते हैं लेकिन इसे लागू नहीं करते हैं? int लिखना (char * str); – ifma

+0

ठीक है, लेकिन दो प्रकार के बीच एक भेद क्यों होना चाहिए? साथ ही, 'w.write (buf) को कॉल करना; '_always_ call' int Writer :: लिखना होगा (const std :: string & str); 'यदि आप इसे' int Writer :: लिखना चाहते हैं (const char * str, int len) ; ', फिर अपने कॉल में लम्बाई पैरामीटर जोड़ें। – InternetAussie

+0

बफर के रूप में std :: vector का उपयोग करें। –

उत्तर

5

C++ आश्चर्य की बात परिणाम उत्पन्न कर सकते अधिभार संकल्प दौरान ICS (Implicit Conversion Sequences) के रूप में आप ध्यान दिया है, और यह भी काफी कष्टप्रद ..

आप आवश्यक इंटरफेस की जरूरत है, तो ध्यान से स्ट्रिंग शाब्दिक बनाम को संभालने के लिए रोजगार टेम्पलेट्स प्रदान कर सकते हैं const char* फियास्को partial ordering से delete अवांछित अधिभार का लाभ उठाकर।

कोड:

#include <iostream> 
#include <string> 
#include <type_traits> 

class Writer 
{ 
public: 
    int write(std::string&&) { std::cout << "int write(std::string)\n"; return 0; } 
    int write(const std::string&) { std::cout << "int write(const std::string& str)\n"; return 0; } 
    int write(const char*, int){ std::cout << "int write(const char* str, int len)\n"; return 0; } 

    template<std::size_t N = 0, typename = std::enable_if_t<(N > 0)> > 
    int write(const char (&)[N]) { std::cout << "int write(string-literal) " << N << " \n"; return 0; } 


    template<typename T> 
    int write(T&&) = delete; 

}; 

int main(){ 
    char* buf = new char[30]; 
    const char* cbuf = buf; 
    Writer w; 

    //w.write(buf);      //Fails! 
    //w.write(cbuf);     //Fails! 
    w.write(buf, 30);     //Ok! int write(const char*, int); 
    w.write(std::string("Haha"));  //Ok! int write(std::string&&); 
    w.write("This is cool");   //Ok! int write(const char (&)[13]); 
} 

प्रिंटों:

int write(const char* str, int len) 
int write(std::string) 
int write(string-literal) 13 

Demo


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

+0

पूर्णता के लिए, क्या आप इसमें शामिल कर सकते हैं कि * सभी * निहित रूपांतरणों को 'std :: string' में अक्षम करने का नकारात्मक पक्ष है? –

+0

@PasserBy, जोड़ा गया। धन्यवाद! – WhiZTiM

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