类类型隐式转换
如果构造函数只接受一个实参,则它实际上定义了转换为此类型的隐式转换机制,有时我们把这种构造函数称作转换构造函数(converting constructor)。即,能通过一个实参调用的构造函数定义了一条从构造函数的参数类型向类类型隐式转换的规则。这种隐式转换仅限于一步转换(即不能连续转换)。class A {
public:
A (char c) {}
A (std::string s) {}
};
在A类中,接受char的构造函数和接受string的构造函数分别定义了从这两种类型向A类型隐式转换的规则。也就是说,在需要使用A的地方,我们可以使用char或者string作为替代:
A a = "Hello";//将string类型隐式转换为A类型
然而在某些情况下隐式类型转换却违背了程序员的本意,因此程序员不希望隐式类型转换的发生,explicit关键字就起到这个作用。
explicit
explicit关键字主要用于构造函数上,explicit关键字可以阻止构造函数进行隐式类型转换。explicit A (char c) {}
将构造函数声明为explicit后,A a = "Hello"; 这条语句将无法通过编译。
关键字explicit只对一个实参的构造函数有效。需要多个实参的构造函数不能用于执行隐式转换,所以无须将这些构造函数指定为explicit的。只能在类内声明构造函数时使用explicit关键字,在类外部定义时不应重复。
只能用于直接初始化
发生隐式转换的一种情况是当我们执行拷贝形式的初始化时(使用=),此时,我们只能使用直接初始化而不能使用explicit构造函数。
显式初始化(强制类型转换)
尽管编译器不会将explicit的构造函数用于隐式转换过程,但是我们可以使用explicit构造函数显式地强制进行转换。毕竟C++标准定义explicit关键字只能阻止隐式转换,并未限制显式转换。总之,发生隐式类型转换,除非是有心利用,否则隐式转换常常带来程序逻辑的错误,这种错误难以察觉。因此,原则上应该将所有构造函数都用explicit修饰,当有心利用时再去解除,这样可以减少错误的发生。
本文部分内容摘自《C++ Primer(中文版)第五版》