C++ 关键字explicit
C++11 之前explicit的作用
关于explicit关键字,先看看MSDN上的解释:
This keyword is a declaration specifier that can only be applied to in-class constructor declarations . An explicit constructor cannot take part in implicit conversions. It can only be used to explicitly construct an object 。
从上面的解释可以看到, explicit关键字的作用: 禁止隐式调用类内的单参数构造函数, 这主要包括如下三层意思:
-
该关键字只能用来修饰类内部的构造函数
-
禁止隐式调用拷贝构造函数
-
禁止类对象之间的隐式转换
例子
#include <string>
#include <iostream>
using namespace std;
class Cxstring {
public:
string _str;
int _size;
Cxstring(int size) {
_size = size;
}
Cxstring(string str) {
_str = str;
}
};
int main() {
Cxstring s1 = 1;
Cxstring s2(2);
Cxstring s6 = 'c';// 这样是OK的, 其实调用的是CxString(int size), 且size等于'c'的ascii码
string a = "aaaa";
Cxstring s3(a);
Cxstring s4("aae");
Cxstring s5 = a;
s1 = s3;
}
上面的例子都能编译通过。但是如果我们将第一个构造函数添加了explicit:
#include <string>
#include <iostream>
using namespace std;
class Cxstring {
public:
string _str;
int _size;
explicit Cxstring(int size) {
_size = size;
}
Cxstring(string str) {
_str = str;
}
};
int main() {
Cxstring s1 = 1; // 这样是不OK的,explicit取消了隐式转换
Cxstring s2(2);
Cxstring s6 = 'c';// 这样是不OK的, explicit取消了隐式转换
string a = "aaaa";
Cxstring s3(a);
Cxstring s4("aae");
Cxstring s5 = a;
s1 = s3;
}
隐式转换到底是什么呢?以上面的一段代码来做例子:
Cxstring s1 = 1;
//相当于
Cxstring temp(1);
Cxstring s1 = temp;
explicit关键字只对有一个参数的类构造函数有效, 如果类构造函数参数大于或等于两个时, 是不会产生隐式转换的, 所以explicit关键字也就无效了
effective c++中说:被声明为explicit的构造函数通常比其non-explicit兄弟更受欢迎。因为它们禁止编译器执行非预期的类型转换,除非我有一个好理由允许构造函数被用于隐式类型转换,否则我会把它声明为explicit.鼓励大家遵循相同的政策。
C++11 之后explicit的新作用
C++11 之后explicit增加了新的作用:
允许explict用来修饰类型转换操作符()上
当然,C++ 之前的作用还保留着。
例子:
class B;
class A
{
public:
explict operator B () const {return B();}
}
void Func(B b);
void main()
{
A a;
B b1(a); //直接构造初始化
B b2 = static_cast<B>(a); //强制类型转换
//其它都不行,拷贝构造
B b3 = a;
Func(a);
}
可以防止()运算符中的隐式转换。
总的来说,explicit关键字的作用主要是禁止隐式转换。