第41课 - 类型转换函数(上)

1. 再论类型转换(隐式转化和强制类型转换)

(1)标准数据类型之间会进行隐式类型安全转换

(2)转换规则

      第41课 - 类型转换函数(上)

 

  8个字节 long: 8个字节 long long: 8个字节 unsigned long: 8个字节

 小类型(占用内存小)--->大类型(占用内存大)-----隐式转化(安全,不会发生程序的截断和数据的丢失)

实验:编程避免不同类型转换,编译器进行的隐式转换很可怕

 1 #include<iostream> 
 2 #include<string>
 3 
 4 using namespace std;
 5 
 6 int main()
 7 {
 8     short s = 'a';
 9     unsigned int ui = 1000; //unsigned_-->int
10     int i = -2000;
11     double d = i;         //小类型初始化大类型是安全的
12 
13     cout << d << endl;  //-2000
14     cout << ui<< endl;  //1000
15     cout << ui+i << endl;    //验证:ui+i =4294966296
16 
17                             //因为i会被转为unsigned int类型,两个无符号整形数相加,变成一个很大的正数。
18     //编程避免隐式类型转换
19 
20     if ((ui + i) > 0)                  //编译器进行隐式类型转换,将i(小类型)转换为unsigned int(大类型) 
21     {
22         cout << "positive" << endl;    //negative
23     }
24     else
25     {
26         cout << "negative" << endl;    
27     }
28 
29     //根据标准数据类型的转换规则s->int。'b'为char,也会被转为int型。所以输出4
30 
31     cout << "sizeof(s+'b')=" << sizeof(s + 'b') << endl;    //4
32                                                                                                                         //编译期将s和b都转换为Int
33     return 0;
34 }

问题:

                            第41课 - 类型转换函数(上)

实验:普通到类类型

 1 #include<iostream>     
 2 #include<string>
 3 
 4 using namespace std;
 5 
 6 //类之间可不可以进行类型转换
 7 class Test
 8 {
 9     int mvalue;
10 public:
11     Test()
12     {
13     }
14 
15     Test(int i)   //转换构造函数
16     {
17         mvalue = i;
18     }
19     Test operator + (const Test& p)
20     {
21         Test ret(mvalue + p.mvalue);
22 
23         return ret;
24     }
25 
26     int value()
27     {
28         return mvalue;
29     }
30     
31 };
32 int main()
33 {
34     Test t;
35 
36     //    t = (Test)5; //类型怎么转换????
37     //  t = Test(5); //直接调用构造函数,会产生一个临时对象,临时对象赋值给t对象,他俩属于Test对象
38                      //编译器进行隐式类型转换-----本质调用转换构造函数
39                         
40     t = 5;        //没有转化构造函数之前,错误
41                 //有转换构造函数定义,等价于t=Test(5); 正确
42 
43     Test r;
44     r = t + 10;      //相当于:r = t + Test(10); 手误10整形,将2个Test对象相加,调用构造函数----error
45 
46     cout << r.value() << endl;  //15  
47 
48     return 0;
49 }

 

2. 普通类型到类类型的转换——转换构造函数

也可以将其他类类型转换到当前类类型

(1)构造函数可以定义不同类型的参数

(2)参数满足下列条件时称为转换构造函数

  ①有且仅有一个参数

  ②参数是基本类型

  ③参数是其它类类型但不是本类的const引用,因为那叫拷贝构造函数

                                 第41课 - 类型转换函数(上)

(3)另一个视角:旧式的C方式强制类型转换

int i = int(1.5);   //将浮点转为整型,有点像函数调用

Test t;
t = Test(100); //老旧的C转换方式,100整形强制类型转换到类类型,本质---调用构造函数 有点像函数调用

 但是这样子隐式转化是不好的,实验说明:和上面一样

Test r;
r = t + 10; //相当于:r = t + Test(10); 手误10整形,将2个Test对象相加,调用构造函数----error

cout << r.value() << endl; //15

怎么解决?????

 第41课 - 类型转换函数(上)

 

3. explicit关键字-----

1)编译器隐式转换行为:

  ①编译器尽力尝试让源码通过编译

第41课 - 类型转换函数(上)
Test t;

t = 100;  //100这个立即数,默认为int型,怎么可能赋值给t对象呢?现在就报错

          //吗?不急,编译器会看看有没有转换构造函数!Ok,发现Test类中定义

          //Test(int i),可以进行转换,默认等价于:t = Test(100);
第41课 - 类型转换函数(上)

  ②隐式类型转换会让程序以意想不到的方式进行工作,是工程中Bug的重要来源

 

(2)杜绝编译器的隐式类型转换explicit关键字

  ①用explicit修饰转换构造函数。这时会阻止编译器隐式地尝试调用这个函数的行为

  ②当转换构造函数explicit修饰时,只能手动进行显式的转换转换方式:

    • A.static_cast<ClassName>(value);   //C++

    • B.ClassName(value);                        //C--手动调用构造函数

    • C.(ClassName)value;    //不推荐

 

 转换构造函数之前加了explicit----编译器不会自动调用转换构造函数,需要手动调用

 1 #include <iostream>
 2 
 3 using namespace std;
 4 
 5 class Test
 6 {
 7     int mValue;
 8 
 9 public:
10 
11     Test() { mValue = 0; }
12 
13     explicit Test(int i)            //转换构造函数
14     {
15         mValue = i;
16     }
17 
18     Test operator + (const Test& p)
19     {
20         Test ret(mValue + p.mValue);
21 
22         return ret;
23     }
24 
25     int value()
26     {
27         return mValue;
28     }
29 
30 };
31 
32 
33 
34 int main()
35 {
36     Test t;
37 
38     //t = 5; //error,将5赋值给t对象,编译器会尝试调用Test(int i)转换构造函数
39 
40              //但由于Test(int i)前面用explicit修饰,以后拒绝了这种尝试。所以
41 
42              //编译不通过。
43 
44 
45     t = static_cast<Test>(5); //相当于 t = Test(5); 原因:Test(int i)被explicit修饰,
46 
47                               //就是告诉编译器要阻止那种通过隐式调用该函数的行为发生。
48 
49                               //只有显式调用Test(int i)(或通过强制类型方式转换的)
50 
51                               //才允许调用这个函数来进行类型的转换。
52 
53 
54     Test r;
55 
56     //r = t + 10;  error
    
    t=(Test)5; //c语言方式,不推荐 57 58 r = t + static_cast<Test>(10); //c++推荐写法 59 60 cout << r.value() << endl; //15; 61 62 return 0; 63 }

 

 

4. 小结

(1)转换构造函数只有一个参数   explicit Test(int i)

(2)转换构造函数参数类型其它类型

(3)转换构造函数类型转换被调用

(4)隐式类型转换工程中Bug的重要来源

(5)explicit关键字用于杜绝编译器这种隐式类型转换的行为

 

上一篇:leetcode每日一题(2020-06-27):41. 缺失的第一个正数


下一篇:leetcode-41-缺失的第一个正数