传统观点认为,采用一个参数(通过使用默认参数显式或有效地)的构造函数应该被标记explicit
,除非它们确实定义了转换(std::string
可以从const char*
后者的一个示例转换)。您自己已经弄清楚了原因,因为隐式转换确实会使生活变得比必须的更难。
一个可能明显的例外是复制构造函数。或者也许另一种方式是考虑大多数类型可以相互转换,因此复制构造函数explicit
大部分时间都没有标记。
虽然看起来标记所有其他类型的构造函数explicit
并没有什么坏处,但我反对它。因为虽然explicit
在 C++03 中对采用多个参数的构造函数没有影响,但它在 C++11 中确实有效。将其放入代码中:
struct foo {
explicit foo(int i);
foo(int i, int j);
explicit foo(int i, int j, int k);
};
foo make_foo()
{
/* Not C++11-specific: */
// Error: no conversion from int to foo
return 42;
// Okay: construction, not conversion
return foo(42);
// Okay: constructions
return foo(42, 42);
return foo(42, 42, 42);
/* C++11 specific: */
// Error: no conversion from int to foo
return { 42 };
// Not an error, not a conversion
return { 42, 42 };
// Error! Constructor is explicit
return { 42, 42, 42 };
// Not an error, direct-initialization syntax
return foo { 42, 42, 42 };
}
我个人觉得在返回的函数中foo
我必须显式地返回不必要的冗长foo { 42, 42, 42 }
。我看不出是什么explicit
在保护我。我真的希望{ initializers... }
语法意味着“从给定的初始化程序构造对象”,并explicit
在将我从无到有的情况下进入其中。(因为{ i }
确实归结为i
在复制初始化的背景下——大多数时候——我很乐意放弃那个。)
所以我想说养成使用explicit
一元构造函数的习惯,而且那些只有.