【发布时间】:2016-12-31 12:25:23
【问题描述】:
使构造函数具有多个参数explicit 有任何(有用的)效果吗?
例子:
class A {
public:
explicit A( int b, int c ); // does explicit have any (useful) effect?
};
【问题讨论】:
使构造函数具有多个参数explicit 有任何(有用的)效果吗?
例子:
class A {
public:
explicit A( int b, int c ); // does explicit have any (useful) effect?
};
【问题讨论】:
直到 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
【讨论】:
explicit 现有语义的逻辑扩展。我个人不会费心制作多参数构造函数explicit。
你会偶然发现它用于大括号初始化(例如在数组中)
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;
}
【讨论】:
@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,在第一次编写方法时这样做可能是值得的。
【讨论】:
explicit,技术支持将被关于该更改的电话淹没,并花费小时解释explicit只是噪音,并且删除它是无害的。就个人而言,我不太擅长预测未来; 现在决定界面应该是什么样子已经够难的了。
这是我对这次讨论的五分钱:
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。
【讨论】: