目录
使用explicit关键字情况二: 虽然有多个参数,但是创建对象时后两个参数可以不传递。
一.类型转换
隐式类型转换
隐式类型转换就是编译器默默地、隐式地、偷偷地进行的数据类型转换,这种转换不需要程序员干预,会自动发生。
#include<iostream>
using namespace std;
int main() {
int a = 10;
double c = a; //自动类型转换
return 0;
}
代码解析:double c=a;表示变量a会在内层空间外部创建一个临时的变量,里面存储a的数值,然后临时变量的内容进行自动类型转换再拷贝给变量c,之后临时变量被销毁。变量a的值是不会进行类型转换的,编译器转换的只是临时变量。
强制类型转换
隐式类型转换是编译器根据代码的上下文环境自行判断的结果,有时候并不是那么“智能”,不能满足所有的需求。如果需要,程序员也可以自己在代码中明确地提出要进行类型转换,这称为强制类型转换。
int main() {
//强制类型转换
cout << (float)a << endl;
return 0;
总结:
强制类型转换是程序员明确提出的、需要通过特定格式的代码来指明的一种类型转换;,隐式类型转换是编译器默默地、隐藏地进行的一种类型转换,不需要在代码中体现出来。换句话说,隐式类型转换不需要程序员干预,强制类型转换必须有程序员干预。
二.类对象之间的隐式类型变换
class Date{
public:
Date(int year)
:_year(year)
{
cout << "Date类的构造函数" << endl;
}
Date(const Date& d) {
_year = d._year;
_month = d._month;
_day = d._day;
cout << "Date类的拷贝构造函数" << endl;
}
~Date() {
_year = 0;
_month = 0;
_day = 0;
cout << "析构函数调用" << endl;
}
private:
int _year;
int _month;
int _day;
};
int main(){
Date d1(2022); //创建对象d1,调用构造函数
Date d2(d1); //创建对象d2,调用拷贝构造
Date d3 = d1; //也是调用拷贝构造,与语句二等价
Date d4 = 2022;
Date& d5 = 2022;
}
代码解析:Date d4=2022;这条语句编译器采用了隐式类型转换,不仅调用了构造函数还调用了拷贝构造函数,原理就是:2022为int型常量,用int去构造一个Date类的临时对象,这就要用到构造函数了,之后,这个临时对象再调用拷贝构造给d4,所以d4._year=2022。
但是编译器采用了隐式类型转换(优化),构造+拷贝构造== > 直接构造。所以d4语句的执行只调用了构造函数!
而Date& d5=2022;也是2022调用构造创建一个临时对象,而d5拷贝构造临时对象,是临时对象的别名。但该句会出现编译错误,因为临时对象具有常性(仅可读),Date&是可读可写,左右权限不等,所以报错。左值应该加const才行。
explicit关键字:
情况一:对于单参构造函数,没有使用explicit修饰,具有类型转换作用。
explicit修饰构造函数,限制了编译器无法使用隐式类型转换--explicit去掉之后,代码可以通过编译。
explicit Date(int year)
:_year(year)
{
cout << "Date类的构造函数" << endl;
}
使用explicit关键字情况二: 虽然有多个参数,但是创建对象时后两个参数可以不传递。
class Date
{
public:
// 2. 虽然有多个参数,但是创建对象时后两个参数可以不传递,没有使用explicit修饰,具
//有类型转换作用
// explicit修饰构造函数,禁止类型转换
Date(int year, int month = 1, int day = 1) //部分缺省
: _year(year)
, _month(month)
, _day(day)
{}
private:
int _year;
int _month;
int _day;
};
int main() {
Date d1 = 2030;
//这个也具有隐式类型转换,自动转换为Date d1(2030);
return 0;
}
C++11版本后:即使构造函数中没有缺省值,对象也可以传所有参数进行隐式类型转换。但需要用一对花括号包含实参。
class Date
{
public:
Date(int year, int month, int day)
: _year(year)
, _month(month)
, _day(day)
{}
private:
int _year;
int _month;
int _day;
};
int main() {
//Date d1 = 2022, 10, 12; //报错
//Date d2 = (2022, 10, 12); //报错
Date d3 = { 2022,10,12 };
//d3具有隐式类型转换,d3这条语句等价于 Date d3(2022,10,12);
const Date& d4 = { 2022,10,12 }; //也涉及隐式类型转换,临时对象具有常性,需要const
//注:以上之所以能进行隐式类型转换,是因为构造函数处没有explicit关键字,
return 0;
}