Explicit constructor taking multiple arguments

前端 未结 4 1076
面向向阳花
面向向阳花 2021-01-30 03:36

Does making a constructor having multiple arguments explicit have any (useful) effect?

Example:

class A {
    public:
        explicit A( in         


        
相关标签:
4条回答
  • 2021-01-30 04:08

    Up until C++11, yeah, no reason to use explicit on a multi-arg constructor.

    That changes in C++11, because of initializer lists. Basically, copy-initialization (but not direct initialization) with an initializer list requires that the constructor not be marked explicit.

    Example:

    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
    
    0 讨论(0)
  • 2021-01-30 04:12

    The excellent answers by @StoryTeller and @Sneftel are the main reason. However, IMHO, this makes sense (at least I do it), as part of future proofing later changes to the code. Consider your example:

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

    This code doesn't directly benefit from explicit.

    Some time later, you decide to add a default value for c, so it becomes this:

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

    When doing this, you're focussing on the c parameter - in retrospect, it should have a default value. You're not necessarily focussing on whether A itself should be implicitly constructed. Unfortunately, this change makes explicit relevant again.

    So, in order to convey that a ctor is explicit, it might pay to do so when first writing the method.

    0 讨论(0)
  • 2021-01-30 04:21

    Here's my five cents to this discussion:

    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;
    }
    

    As you can easily see, explicit prevents from using initializer list alongside with bar function bacause the constructor of struct Bar is declared as explicit.

    0 讨论(0)
  • 2021-01-30 04:23

    You'd stumble upon it for brace initialization (for instance in arrays)

    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;
    }
    
    0 讨论(0)
提交回复
热议问题