2011-11-24 22 views
8

मुझे दो डिफ़ॉल्ट पैरामीटर के साथ कन्स्ट्रक्टर लिखना है।डिफ़ॉल्ट तर्क C++ को कैसे छोड़ें?

func(int arg1 , char* arg2 = "arg2", int arg3 = 1) //example 

मैं परिदृश्य में जहाँ निर्माता कहा जाता है प्रदान की कर रहा हूँ और एक मूल्य arg1 और arg2 और arg3 को दिया जाता है एक डिफ़ॉल्ट मान का उपयोग करने की उम्मीद है। फिर एक और ऑब्जेक्ट तत्काल होता है और arg1 और arg3 पर मान दिया जाता है, और arg2 के लिए डिफ़ॉल्ट मान का उपयोग होने की उम्मीद है। अब समस्या यह है कि, आप डिफ़ॉल्ट पैरामीटर को "छोड़ नहीं सकते" है जो मैं पाठ और ऑनलाइन से पढ़ रहा हूं। यह डिफ़ॉल्ट पैरामीटर को ओवरलोड होने की अपनी पसंद से ऑर्डर करने का कह रहा है, लेकिन परिदृश्य में एक डिफ़ॉल्ट पैरामीटर होता है जबकि दूसरा नहीं होता है। इस प्रश्न के संकेत मुझे पैरामीटर/तर्कों को पुन: व्यवस्थित करने के लिए कहते हैं। हालांकि, मैंने जो भी किया है, वह इस मुद्दे को हल करने में सक्षम नहीं है।

इसके अलावा, अधिभारित कन्स्ट्रक्टर का उपयोग नहीं किया जा सकता है। यह एक कन्स्ट्रक्टर द्वारा किया जाना है।

तो कोई ऐसा कैसे करेगा? मैं स्टंप्डया और थोड़ा इस :(

+6

आप इसे एक एकल फ़ंक्शन परिभाषा के साथ C++ में नहीं कर सकते हैं। यह देखते हुए कि कोई अन्य समाधान आपके पास विचित्र बाधाओं का उल्लंघन करता है, जो आप चाहते हैं वह असंभव है। शायद आप एक अलग भाषा का उपयोग कर सकते हैं। –

+1

यह होमवर्क है? – xmoex

+0

क्या आप ऑब्जेक्ट के 'वेक्टर' का उपयोग नहीं कर सकते? इस तरह आप जो चाहते थे उसे पारित कर सकते हैं और 'शून्य' प्रविष्टियों के आधार पर पारित नहीं किया गया था। – MoonKnight

उत्तर

6

इसके अलावा, अतिभारित कंस्ट्रक्टर्स नहीं किया जा सकता। यह एक निर्माता द्वारा किया जा सकता है से अधिक पागल हो रहा हूँ।

एकमात्र कारण मैं के बारे में सोच सकते हैं इस आवश्यकता के लिए वैकल्पिक तर्कों का एक ही प्रकार है। उस स्थिति में, आप अटक गए हैं और आप named constructor और/या named parameter मुहावरे देखना चाहते हैं।

अन्यथा, अतिरिक्त कन्स्ट्रक्टर को परिभाषित करें। कुछ डुप्लिकेशंस wrt शामिल हो सकता है। डिफ़ॉल्ट मान।

Foo(int arg1 , char const *arg2 = "arg2", int arg3 = 1) 
{ 
    construct(arg1, arg2, arg3); 
} 

Foo(int arg1, int arg3) 
{ 
    construct(arg1, "arg2", arg3); 
} 
+1

वे कुछ वाकई अच्छे मुहावरे हैं, लिंक साझा करने के लिए धन्यवाद। स्टैक ओवरफ़्लो के बारे में एक अद्भुत चीज यह है कि आप यादृच्छिक रूप से धागे को समझ सकते हैं और कुछ अच्छी चीजें सीख सकते हैं :) +1 –

0

पेकुलियर प्रतिबंध, कि केवल एक ही कन्स्ट्रक्टर होना चाहिए। के बाद से एक स्ट्रिंग गैर स्थिरांक char* को शाब्दिक से रूपांतरण पदावनत और मूर्ख है,

#include <iostream> 

// cheap and cheerful Boost.Variant 
struct StringOrInt { 
    char *s; 
    int i; 
    bool is_string; 
    StringOrInt(char *s) : s(s), i(0), is_string(true) {} 
    StringOrInt(int i) : s(0), i(i), is_string(false) {} 
    bool isInt() { return !is_string; } 
    int asInt() { return i; } 
    char *asString() { return s; } 
}; 

struct Foo { 
    int m1; 
    char *m2; 
    int m3; 
    Foo(int arg1, StringOrInt arg2 = "arg2", int arg3 = 1) : m1(arg1) { 
     if (arg2.isInt()) { 
      arg3 = arg2.asInt(); 
      arg2 = "arg2"; 
     } 
     m2 = arg2.asString(); 
     m3 = arg3; 
    } 
    void print() { 
     std::cout << m1 << " " << m2 << " " << m3 << "\n"; 
    } 
}; 

int main() { 
    Foo(1, "HelloWorld").print(); 
    Foo(1, 2).print(); 
} 

ध्यान दें कि जीसीसी के साथ इस चेतावनी उत्पन्न करता है: यहाँ निकटतम मैं के बारे में सोच सकते हैं। लेकिन आपने यही पूछा है, और इसे ठीक करने के लिए ताकि char* पैरामीटर और डेटा सदस्य const char* पर्याप्त आसान हो।

एक महत्वपूर्ण कमजोरी यह है कि इससे आपको Foo(1,2,3) लिखना बंद नहीं होता है। संकलन समय पर यह जांचने के लिए मुझे लगता है कि आपको कई रचनाकारों की आवश्यकता है। रनटाइम पर इसे जांचने के लिए, आप तीसरे पैरामीटर को किसी अन्य वर्ग, DefaultOrInt में बना सकते हैं, जहां Default इस उद्देश्य के लिए उपयोग किया जाने वाला एक प्रकार है, जो arg3 के डिफ़ॉल्ट मान के रूप में उपयोग किए जाने वाले केवल एक मान का समर्थन करता है। फिर यदि arg2.isInt() सत्य है, तो arg3.isInt() चेक करें और यदि logic_error फेंक नहीं है।

0

यदि आपको दूसरे पैरामीटर के लिए कोई मूल्य नहीं है तो आपको एक खाली सी-स्ट्रिंग पास करने की अनुमति है, तो आप एक सहायक फ़ैक्टर का उपयोग कर सकते हैं जो arg2 की जांच करेगा और यदि यह खाली है तो डिफ़ॉल्ट मान वापस कर देगा। कुछ इस तरह:

#define DEFAULT_ARG "arg2" 

struct helper_class { 
    char* operator()(char* arg) 
    { 
     if (*arg) return arg; else return DEFAULT_ARG; 
    } 
} helper; 

class func { 
    public: 
    func(int arg1 , char* arg2 = "arg2", int arg3 = 1) {} 
}; 

int main() 
{ 
    func f1(42, helper(""), 9001); // default 2nd argument 
    func f2(42, helper("Its over 9000!")); 
} 

नहीं सुंदर, मुझे पता है ...

0

अभी आप std::bind उपयोग कर सकते हैं आपरेशन के या C++ 14/17 आप लैम्ब्डा समारोह का उपयोग करें और पूरा कर सकते हैं में इस तरह करने के लिए वही।

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