100

使具有多个参数的构造函数explicit有任何(有用的)效果吗?

例子:

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

4 回答 4

134

直到 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
于 2016-08-24T11:35:37.803 回答
34

您会偶然发现它进行大括号初始化(例如在数组中)

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;
}
于 2016-08-24T11:34:00.897 回答
25

@StoryTeller 和 @Sneftel 的出色回答是主要原因。但是,恕我直言,这是有道理的(至少我这样做了),作为以后对代码进行校对的一部分。考虑你的例子:

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,在第一次编写方法时这样做可能是值得的。

于 2016-08-24T11:40:24.887 回答
10

这是我对这次讨论的五分钱:

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.

于 2016-08-24T12:14:31.700 回答