仅含一个参数的构造函数和除了第一个参数外其余参数都有默认值的多参构造函数承担了两个角色。
- 是个构造函数;
- 是个默认且隐含的类型转换操作符。
explicit是个C++关键字,其作用是指定仅有一个参数或除第一个参数外其它参数均有默认值的类构造函数不能作为类型转化操作符被隐含的使用,防止该类的对象直接被对应内置类型隐式转化后赋值,从而规定这个构造函数必须被明确调用。
#include <iostream>
#include <string>
#include <vector>
#include <string>
using namespace std;
class A
{
public:
A(int i = 1)
{
m_a = i;
}
void mcout();
private:
int m_a;
};
void A::mcout()
{
cout << m_a << endl;
}
int main()
{
A s;//这里并没有重载‘=’运算符,但是却可以把内置的int类型赋值给A
s.mcout();
s = 10;//实际上,10被隐式转换成下面形式
//s = A temp(10);
s.mcout();
system("pause");
return 0;
}
结果
1
10
在构造函数中加上explicit关键字来修饰类的构造函数
#include <iostream>
#include <string>
#include <vector>
#include <string>
using namespace std;
class A
{
public:
explicit A(int i = 1)
{
m_a = i;
}
void mcout();
private:
int m_a;
};
void A::mcout()
{
cout << m_a << endl;
}
int main()
{
A s;//如果构造函数形参没有默认值则会失败
s.mcout();
//s = 10;//隐式转换会报错
s = A(20);//显示转换还是可以的
s.mcout();
system("pause");
return 0;
}
结果
1
20
再看一个列子
#include <iostream>
#include <string>
#include <vector>
#include <string>
using namespace std;
class A
{
public:
A(int a):m_a(a){}
void macout()
{
cout << m_a << endl;
}
private:
int m_a;
};
class B
{
public:
explicit B(int b) :m_b(b) {}
private:
int m_b;
};
int main()
{
A test1 = 12;
B test2(13);
//B test3 = 14;
system("pause");
return 0;
}
编译时t3那一行会报错:提示:无法从“int”转化为“B”。注释掉t3那一行,t1能编译通过,调试时发现t1中的成员变量m_a已被赋值成功。
通过以上两个例子我们可得:对于仅有一个参数或除第一个参数外其余参数均有默认值的类构造函数,尽可能使用explicit关键字修饰。另注意:当类的构造函数的声明和定义分别在两个文件里时,explicit只能写在构造函数的声明中,不能写在定义中。