第41课 - 类型转换函数(上)
1. 再论类型转换
(1)标准数据类型之间会进行隐式的类型安全转换
(2)转换规则:
【实例分析】有趣的隐式类型转换 41-1.cpp
#include <iostream> using namespace std; int main() { short s ='a'; unsigned int ui = 1000; int i = -2000; double d = i; cout << "d = " << d << endl; //d = -2000 cout << "ui = " << ui << endl; //ui = 1000; cout << "ui + i = " << ui + i << endl; //ui + i = 4294966296i。 //因为i会被转为unsigned int类型, //变成一个很大的正数。 if ((ui + i) > 0) cout << "Positive" << endl; //该行被输出,因为ui+i变成一个很大的正数 else cout << "Negative" << endl; //负数 //根据标准数据类型的转换规则s->int。'b'为char,也会被转为int型。所以输出4 cout << "sizeof(s + 'b') = " << sizeof(s + 'b') << endl; //输出4,即两个int类型相加 return 0; }
运行结果:
2. 普通类型到类类型的转换——转换构造函数
(1)构造函数可以定义不同类型的参数
(2)参数满足下列条件时称为转换构造函数
①有且仅有一个参数
②参数是基本类型
③参数是其它类类型(但不是本类的const引用,因为那叫拷贝构造函数)
(3)另一个视角:旧式的C方式强制类型转换
int i = int(1.5); //将浮点转为整型,有点像函数调用 Test t;
t = Test(100); //老旧的C转换方式,有点像函数调用
3. explicit关键字
(1)编译器隐式转换行为:
①编译器会尽力尝试让源码通过编译
Test t; t = 100; //100这个立即数,默认为int型,怎么可能赋值给t对象呢?现在就报错 //吗?不急,编译器会看看有没有转换构造函数!Ok,发现Test类中定义 //Test(int i),可以进行转换,默认等价于:t = Test(100);
②隐式类型转换会让程序以意想不到的方式进行工作,是工程中Bug的重要来源。
(2)杜绝编译器的隐式类型转换:explicit关键字
①用explicit修饰转换构造函数。这时会阻止编译器隐式地尝试调用这个函数的行为。
②当转换构造函数被explicit修饰时,只能手动进行显式的转换,转换方式:
-
-
A.static_cast<ClassName>(value);
-
B.ClassName(value);
-
C.(ClassName)value; //不推荐
-
【编程实验】普通类型→类类型 41-2.cpp
#include <iostream> using namespace std; class Test { int mValue; public: Test(){mValue = 0;} explicit Test(int i) //转换构造函数 { mValue = i; } Test operator + (const Test& p) { Test ret(mValue + p.mValue); return ret; } int value() { return mValue; } }; int main() { Test t; //t = 5; //会报错,将5赋值给t对象,编译器会尝试调用Test(int i)转换构造函数 //但由于Test(int i)前面用explicit修饰,以后拒绝了这种尝试。所以 //编译不通过。 t = static_cast<Test>(5); //相当于 t = Test(5); 原因:Test(int i)被explicit修饰, //就是告诉编译器要阻止那种通过隐式调用该函数的行为发生。 //只有显式调用Test(int i)(或通过强制类型方式转换的) //才允许调用这个函数来进行类型的转换。 Test r; //r = t + 10;//相当于:r = t + Test(10); r = t + static_cast<Test>(10); cout << r.value() << endl; //15; return 0; }
运行结果:
4. 小结
(1)转换构造函数只有一个参数
(2)转换构造函数的参数类型是其它类型
(3)转换构造函数在类型转换时被调用
(4)隐式类型转换是工程中Bug的重要来源
(5)explicit关键字用于杜绝编译器这种隐式类型转换的行为