一、explicit 的意义
先说作用
主要是为了防止发生隐式转换
那么,什么叫隐式转换呢
看下列代码
int main(int argc, char* argv[])
{
int a = 3; // int 类型
double b = a; // a 被隐式转换成 double 在赋值给 b
return 0;
}
隐式转换总是编译器自动完成的,从小字节自动隐式转换成大字节
但反过来的话,友好的编译器会给我们发出警告,例如以下
int main(int argc, char* argv[])
{
double a = 3;
int b = a;
return 0;
}
给出警告
warning C4244: “初始化”: 从“double”转换到“int”,可能丢失数据
这样的方式极大的方便了我们
在方便的同时也有着容易犯错的地方
看下列代码
int main(int argc, char* argv[])
{
double a = 5 / 2;
std::cout << a << std::endl;
return 0;
}
从数学的角度来看,我们所想的,a 应该是 2.5
但从运行结果来说,它不是 2.5
因为隐式,所以看不见
看不见的时候,就会有一些意想不到的东西
当复杂的环境的时候,往往意想不到的都是灾难级别的存在
那么如何避免
那就是强调显示出来
明确执行
int main(int argc, char* argv[])
{
double a = (double)5 / (double)2;
std::cout << a << std::endl;
return 0;
}
这就是我们想要的结果
而今天讨论的 explicit 就是这样的作用:显示,强调
二、explicit 的用途
考虑以下代码
#include <iostream>
class A {
public:
A(int a):_value(a){}
int value() { return _value; }
private:
int _value;
};
int main(int argc, char* argv[])
{
A a = 3;
std::cout << a.value() << std::endl;
return 0;
}
编译是没有问题的,也可以运行,达到我们预期的目的
A a = 3; // 存在隐式转换
也没有说这样的不好,至于风险的上边已经分析过
想要强调用户使用时必须要显式调用
这时,就可以用 explicit 去修饰一下了
修改代码
编译器不能隐式转换了
那怎么使用呢,以下两种方式都可以
#include <iostream>
class A {
public:
explicit A(int a):_value(a){}
int value() { return _value; }
private:
int _value;
};
int main(int argc, char* argv[])
{
A a = A(3);
A b(4);
std::cout << a.value() << std::endl;
std::cout << b.value() << std::endl;
return 0;
}
当有构造函数有多个参数时,比如
class A {
public:
A(int a, int b):_value1(a), _value2(b){}
int value1() { return _value1; }
int value2() { return _value2; }
private:
int _value1;
int _value2;
};
你不能多个赋值,比如这样
int main(int argc, char* argv[])
{
A a = 3,4
return 0;
}
但 C++11 你可以这样赋值赋值,也是发生隐式转换
int main(int argc, char* argv[])
{
A a = { 3 , 4};
return 0;
}
#include <iostream>
class A {
public:
A(int a, int b ):_value1(a), _value2(b){}
int value1() { return _value1; }
int value2() { return _value2; }
private:
int _value1;
int _value2;
};
int main(int argc, char* argv[])
{
A a = { 3 , 4};
std::cout << a.value1() << std::endl;
std::cout << a.value2() << std::endl;
return 0;
}
加上 explicit
存在默认参数且只有一个参数默认值的情况
当然这也是跟一个参数一样意思了
#include <iostream>
class A {
public:
A(int a, int b = 0):_value1(a), _value2(b){}
int value1() { return _value1; }
int value2() { return _value2; }
private:
int _value1;
int _value2;
};
int main(int argc, char* argv[])
{
A a = 3;
return 0;
}
加上 explicit
三、_End
既然编译器能自动发生隐式转换,这么好用方便,为何还要 explicit
存在即合理
存在即合理
存在即合理