C++构造函数explicit关键字
前阵在看muduo源码的时候,发现很多构造函数用到了explicit
关键字,坐了一天的火车今天刚好没事花一点时间稍微看了一蛤。
首先,这个explicit关键字针对的场景是只有一个参数的构造函数
,因为这样的构造函数除了是一个构造器以外,还有一个默认的隐式类型转换——形参类型到类类型的隐式转换。
看一个例子:
#include <iostream>
using namespace std;
class Foo
{
public:
// single parameter constructor, can be used as an implicit conversion
Foo(int foo) : m_foo(foo)
{
}
int GetFoo() { return m_foo; }
private:
int m_foo;
};
int doFoo(Foo f)
{
return f.GetFoo();
}
int main(int argc, char**argv)
{
int i = doFoo(42);
cout << "i=" << i << endl;
system("pause");
return 0;
}
上述main函数中,虽然在调用doFoo()
函数时,实参不是Foo
类型而是int
类型,但是Foo
类中包含了单个int
类型的参数的构造函数,因此,此时构造函数就可以用来将实参转换成合适的类型。
而explicit
关键字,正是阻止这种隐式转换行为,比如说,当我们将构造函数的定义前加上该关键字:
explicit Foo(int foo) : m_foo(foo)
{
}
此时,main函数中将会出现error:
int i = doFoo(42);//error:不存在int转换到Foo的适当构造函数。
这个时候,我们只能做如下调用:
int i = doFoo(Foo(42));
也就是说,我们必须显示地去调用构造函数。
那么,这个关键字有什么用呢,举个例子:
比如说,有一个构造函数MyString::MyString(int size)
,用来构造特定大小的字符串;而还有一个函数print(MyString &)
,当你调用print(3)
时,你可能是想要打印字符串”3”,而实际上,却打印了一个大小为3的空串。
NOTE:
在Effective C++导读中提到:
“被声明为explicit的构造函数通常比non-explicit更加受欢迎,因为它们禁止编译器执行非预期(往往也不被期望)的类型转换。除非我有一个好理由允许构造函数被用于隐式转换,否则我会把它声明为explicit。我鼓励你遵循相同的政策。”
参考:
1.http://stackoverflow.com/questions/121162/what-does-the-explicit-keyword-in-c-mean
2.http://www.cnblogs.com/cutepig/archive/2009/01/14/1375917.html
3.Effective C++