带多个参数的显式构造函数
Posted
技术标签:
【中文标题】带多个参数的显式构造函数【英文标题】:Explicit constructor taking multiple arguments 【发布时间】:2016-12-31 12:25:23 【问题描述】:使构造函数具有多个参数explicit
有任何(有用的)效果吗?
例子:
class A
public:
explicit A( int b, int c ); // does explicit have any (useful) effect?
;
【问题讨论】:
【参考方案1】:直到 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
【讨论】:
我认为用“我为什么要那个”或“这什么时候有用”的解释来回答会更好。 @MateuszL Edgar 的回答可能是最好的论据,说明它为什么有用(并且可以说值得打勾)。然而,它那里的原因仅仅是因为它是explicit
现有语义的逻辑扩展。我个人不会费心制作多参数构造函数explicit
。【参考方案2】:
你会偶然发现它用于大括号初始化(例如在数组中)
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[] = A1,2, A3,4; // OK
A a2[] = 1,2, 3,4; // Error
return 0;
【讨论】:
【参考方案3】:@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
只是噪音,并且删除它是无害的。就个人而言,我不太擅长预测未来; 现在决定界面应该是什么样子已经够难的了。
@PeteBecker 说得好。我个人认为这两种情况是不对称的,并且在使参数默认(或删除它们)以无意中使类隐式构造时更为常见,然后同时实际意识到回想起来应该是这样。话虽如此,这些都是“软”考虑,可能因人/项目/等而异,甚至只是品味问题。【参考方案4】:
这是我对这次讨论的五分钱:
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
。
【讨论】:
以上是关于带多个参数的显式构造函数的主要内容,如果未能解决你的问题,请参考以下文章
operator== 和 boost::detail::atomic_count 中的显式构造函数?