在写类的构造函数时, 可能经常就会用到explicit
关键字, 而它的具体作用就是 :
- 只能用来修饰构造函数
- 要求修饰的构造函数必须显示调用
- 禁止隐式转换
具体先来看一个例子:
class ExplicitClass
{
public:
ExplicitClass(int size) : size(size) {}
ExplicitClass(const char *str) : str(str) {}
private:
int size;
const char *str;
};
void fun(ExplicitClass ex)
{
}
int main()
{
fun(2);
fun("const char *");
ExplicitClass ex1 = 0;
ExplicitClass ex2 = "const char *";
exit(EXIT_SUCCESS);
}
两次调用fun函数, 但是调用的构造函数却不一样, 但是从用户上看, 可能只知道fun函数可以接收int
和char *
类型的参数, 却不知这是调用了一个类的两中不同的构造函数; 同样, 直接对对象进行初始化时, 默认执行了隐式转换, 这可能让人忘了这是一个类, 这便是隐式转换的风险.
当加上explicit
关键字时, 也就只允许显示的调用构造函数, 禁止了隐式转换.
class ExplicitClass
{
public:
explicit ExplicitClass(int size) : size(size) {}
explicit ExplicitClass(const char *str) : str(str) {}
private:
int size;
const char *str;
};
void fun(ExplicitClass ex)
{
}
int main()
{
fun(2); // error
fun("const char *"); //error
ExplicitClass ex1 = 0; // error
ExplicitClass ex2 = "const char *"; // error
exit(EXIT_SUCCESS);
}
上式的调用就用报错. 而此时我们必须显示的来调用
fun(ExplicitClass(0));
ExplicitClass ex2 = ExplicitClass("const char *");
这样虽然多写了几个单词, 但是调用清晰明了.
注意 : explicit
只能在声明时出现, 类外定义时不应该出现.