使具有多个参数class A {
public:
explicit A( int b, int c ); // does explicit have any (useful) effect?
};
的构造函数具有任何(有用)效果吗?
示例:
{{1}}
答案 0 :(得分:94)
直到C ++ 11,是的,没有理由在多arg构造函数上使用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
答案 1 :(得分:23)
你偶然发现了大括号初始化(例如在数组中)
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;
}
答案 2 :(得分:21)
@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
,在第一次写这个方法时可能会这样做。
答案 3 :(得分:5)
这是我讨论的五分钱:
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
。