C++单参数构造函数与explicit
单参数构造函数比较特殊,在这种函数中,仅含有一个非默认参数(也就是未指定初始值的参数)
比如如下代码定义一个MyClass
类,它的构造函数就是单参数的。在调用时,该构造函数打印提示信息,并指明传入的a值是多少:
class MyClass
{
public:
MyClass(int a, int b = 3)
{
cout << "use the single-param constructor (a = " << a << ")" << endl;
}
void func(MyClass mycls)
{
cout << "use func";
}
};
单参数构造函数之所以特殊,是因为在声明一个MyClass类的对象并且对它初始化时,可以使用一般的方法,也可以使用赋值运算符。并且编译器会为我们生成一个赋值运算符的重载:
//main.cpp
MyClass mycls(0); // 使用一般方法初始化 (*0)
MyClass mycls1 = 1; // 使用赋值运算符初始化 (*1)
mycls = 2; // 使用编译器为我们重载的赋值运算符,
// 也会调用构造函数 (*2)
注意MyClass的func函数,它接受一个MyClass类。此时传入类当然是对的,但由于类的构造函数为单参数的,所以还可以这么调用:
mycls.func(3); // 调用构造函数,并调用func (*3)
以上代码输出结果为:
(*1),(*2)和(*3)都看起来不太符合常理,他们都是正确的,但最好能避免。因为实际运用中,使用这种方式使代码可读性下降了很多,并且这种用法都发生了隐式类型转换。
比如一个数组类MyArray
有单参数构造函数,指定数组的初始大小。使用MyArray arr(3);
比较好理解是把arr初始化长度为3,而使用MyArray arr = 3
不具有什么意义。
为了避免这种隐式类型转换以及提高代码可读性,可以在构造函数面前加上explicit
关键字。它指明使用构造函数时禁止发生隐式转换,加上后(*1)(*2)(*3)均不能通过编译
并且,写构造函数的时候最好都加上explicit
,这是个好习惯(当然也有例外,比如使用初始化列表的时候)