阅读以下博客后:
http://xania.org/200711/ambiguously-overloading
我开始问自己“我不应该总是显式定义我的构造函数吗?”
所以我开始阅读更多的内容,而不是发现这篇文章:
http://www.sjbrown.co.uk/2004/05/01/always-use-explicit/
这展示了另一个例子,也解释了他背后的想法。 但这当然是一位博主的想法。
我很高兴听到你们中的一些人的意见,你们对这种方式的看法,你们对这个主题的经验是什么,以及任何一种方式的一些例子都会很好。
传统的观点是,构造函数采用一个参数(通过使用默认参数显式地或有效地)应该标记为
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
的习惯,仅限这些。