仅含一个参数的构造函数和除了第一个参数外其余参数都有默认值的多参构造函数承担了两个角色。
1. 是个构造函数;2 .是个默认且隐含的类型转换操作符。
explicit是个C++关键字,其作用是指定仅有一个参数或除第一个参数外其它参数均有默认值的类构造函数不能作为类型转化操作符被隐含的使用,防止该类的对象直接被对应内置类型隐式转化后赋值,从而规定这个构造函数必须被明确调用。
我们通过例子来直观的说明:
#include <iostream> using namespace std; class A { public: A(int i = 5) { m_a = i; } private: int m_a; }; int main() { A s; //我们会发现,我们没有重载'='运算符,但是却可以把内置的int类型赋值给了对象A. s = 10; //实际上,10被隐式转换成了下面的形式,所以才能这样. //s = A temp(10); system("pause"); return 0; }
此时,我们发现s的成员变量m_a已将被更改了。
看看我们在类A的构造函数前加上explicit关键字会发生什么。
#include <iostream> using namespace std; class A { public: //这里用explicit关键词来修饰类构造函数. explicit A(int i = 5, int j = 10) { m_a = i; m_b = j; } private: int m_a; int m_b; }; int main() { A s; //这样直接赋值,会被提示错误,因为explicit抑制隐式转换的进行 s = 10;//这样会报错!!! //当然显示转换还是可以的. s = A(20); system("pause"); return 0; }
再来看一个例子。
#include <iostream> using namespace std; class Test1 { public : Test1(int num):n(num){} private: int n; }; class Test2 { public : explicit Test2(int num):n(num){} private: int n; }; int main() { Test1 t1 = 12; Test2 t2(13); Test2 t3 = 14; return 0; }
编译时t3那一行会报错:提示:无法从“int”转化为“Test2”。注释掉t3那一行,t1能编译通过,调试时发现t1中的成员变量n已被赋值成功。
通过以上两个例子我们可得:对于仅有一个参数或除第一个参数外其余参数均有默认值的类构造函数,尽可能使用explicit关键字修饰。
另注意:当类的构造函数的声明和定义分别在两个文件里时,explicit只能写在构造函数的声明中,不能写在定义中。