कई तर्क लेने वाले स्पष्ट निर्माता


88

क्या एक तर्क बनाने वाले के पास कई तर्क होते explicitहैं (कोई उपयोगी) प्रभाव होता है?

उदाहरण:

class A {
    public:
        explicit A( int b, int c ); // does explicit have any (useful) effect?
};

जवाबों:


120

C ++ 11 तक, हाँ, explicitमल्टी-आर्ग कंस्ट्रक्टर पर उपयोग करने का कोई कारण नहीं ।

प्रारंभिक सूचियों के कारण C ++ 11 में परिवर्तन होता है। मूल रूप से, प्रारंभिक-सूची के साथ प्रतिलिपि-आरंभ (लेकिन प्रत्यक्ष प्रारंभ नहीं) के लिए आवश्यक है कि निर्माणकर्ता को चिह्नित नहीं किया जाए explicit

उदाहरण:

struct Foo { Foo(int, int); };
struct Bar { explicit Bar(int, int); };

Foo f1(1, 1); // ok
Foo f2 {1, 1}; // ok
Foo f3 = {1, 1}; // ok

Bar b1(1, 1); // ok
Bar b2 {1, 1}; // ok
Bar b3 = {1, 1}; // NOT OKAY

5
मुझे लगता है कि यह उत्तर "मुझे क्यों चाहिए" या "यह उपयोगी कब है" स्पष्टीकरण के साथ बेहतर होगा।
मेटुसज़्ल

@MateuszL एडगर का जवाब शायद सबसे अच्छा तर्क देता है कि यह उपयोगी क्यों हो सकता है (और यकीनन टिक के हकदार हैं)। कारण यह है वहाँ है, हालांकि, क्योंकि इसके लिए मौजूदा अर्थ विज्ञान का तार्किक विस्तार है explicit। मैं व्यक्तिगत रूप से मल्टी-आर्ग कंस्ट्रक्टर बनाने से परेशान नहीं होता explicit
स्नेफेल

31

आप इसे ब्रेस इनिशियलाइज़ेशन के लिए ठोकर देंगे (उदाहरण के लिए सरणियों में)

struct A {
        explicit A( int b, int c ) {}
};

struct B {
         B( int b, int c ) {}
};

int main() {
    B b[] = {{1,2}, {3,5}}; // OK

    A a1[] = {A{1,2}, A{3,4}}; // OK

    A a2[] = {{1,2}, {3,4}}; // Error

    return 0;
}

24

@StoryTeller और @ स्नेफ्टेल द्वारा उत्कृष्ट उत्तर मुख्य कारण हैं। हालांकि, IMHO, यह समझ में आता है (कम से कम मैं इसे करता हूं), भविष्य के प्रमाण के हिस्से के रूप में बाद में कोड में परिवर्तन होता है। अपने उदाहरण पर विचार करें:

class A {
    public:
        explicit A( int b, int c ); 
};

इस कोड से सीधे लाभ नहीं होता है explicit

कुछ समय बाद, आप के लिए एक डिफ़ॉल्ट मान जोड़ने का निर्णय लेते हैं c, इसलिए यह इस प्रकार है:

class A {
    public:
        A( int b, int c=0 ); 
};

ऐसा करते समय, आप cपैरामीटर पर ध्यान केंद्रित कर रहे हैं - पूर्वव्यापी में, इसका डिफ़ॉल्ट मान होना चाहिए। जरूरी नहीं कि Aआप खुद ही इसका निर्माण करें। दुर्भाग्य से, यह परिवर्तन explicitफिर से प्रासंगिक बनाता है ।

इसलिए, यह बताने के लिए कि एक ctor है explicit, यह ऐसा करने के लिए भुगतान कर सकता है जब पहली विधि लिख रहा हो।


लेकिन उस मामले के बारे में क्या है जब अनुरक्षक उस डिफ़ॉल्ट को जोड़ता है और निष्कर्ष निकालता है कि परिणाम एक कंवर्टर कंस्ट्रक्टर के रूप में उपलब्ध होना चाहिए ? अब उन्हें यह हटाना होगा कि explicitयह हमेशा के लिए है, और तकनीकी सहायता उस परिवर्तन के बारे में कॉल के साथ जल जाएगी और यह बताते हुए घंटों बिताएगी कि explicitबस शोर था, और इसे हटाना हानिरहित है। व्यक्तिगत रूप से, मैं भविष्य की भविष्यवाणी करने में बहुत अच्छा नहीं हूँ; यह तय करना काफी कठिन है कि एक इंटरफ़ेस को अब कैसा दिखना चाहिए ।
पीट बेकर

@PeteBecker यह एक अच्छा बिंदु है। मुझे व्यक्तिगत रूप से लगता है कि दो मामले असममित हैं, और यह बहुत अधिक सामान्य है जब मापदंडों को डिफ़ॉल्ट रूप से (या उन्हें हटाकर) अनजाने में वर्ग को अनुमानित रूप से रचनात्मक बना दिया जाता है, तो वास्तव में एक ही समय में एहसास होता है कि पूर्वव्यापी में ऐसा होना चाहिए। कहा जा रहा है कि, ये "नरम" विचार हैं, और लोगों / परियोजनाओं / आदि के बीच भिन्न हो सकते हैं, या यहां तक ​​कि सिर्फ स्वाद की बात हो सकती है।
अमी तेवरी

8

यहाँ इस चर्चा के लिए मेरे पाँच सेंट हैं:

struct Foo {
    Foo(int, double) {}
};

struct Bar {
    explicit Bar(int, double) {}
};

void foo(const Foo&) {}
void bar(const Bar&) {}

int main(int argc, char * argv[]) {
    foo({ 42, 42.42 }); // valid
    bar({ 42, 42.42 }); // invalid
    return 0;
}

जैसा कि आप आसानी से देख सकते हैं, फ़ंक्शन के explicitसाथ इनिशियलाइज़र सूची का उपयोग करने से रोकता है barक्योंकि निर्माता के struct Barरूप में घोषित किया गया है explicit

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.