1、再论类型转换
- 标准数据类型之间会进行隐式类型转换
- 转换规则如下
#include <iostream>
using namespace std;
int main()
{
short s = 'a';
unsigned int ui = 1000;
int i = -2000;
double d = i;
cout << d << endl;
if (ui + i > 0) //默认转换成unsigned int类型进行运算,结果大于0
{
cout << "Postive" << endl;
}
else
{
cout << "Negative" << endl;
}
cout << ui + i << endl;
cout << sizeof(s + 'c') << endl;
return 0;
}
其实这个程序在C语言里面都写过,第12条语句会默认转换成unsigned int类型进行运算,结果大于0。那上面那个 ui + i 的结果是怎么算的呢?这两个会先转换成无符号数,-2000用补码表示,1000用原码表示,两个相加刚好就是232-1000,就是上面那个数的值。后面那个sizeof()里面主要用到的是整形提升的原理,低于int运算会先转换成int运算。
2、提出问题
普通类型与类类型之间能否进行类型转换?类类型之间能否进行类型转换?先试验一下
#include <iostream>
using namespace std;
class Test
{
};
int main()
{
Test t;
t = (Test)5;
return 0;
}
很明显,这样写普通类型与类类型之间就不能进行类型转换。如果在类里面添加构造函数呢?
#include <iostream>
using namespace std;
class Test
{
private:
int i;
public:
Test(int i = 0)
{
this->i = i;
}
};
int main()
{
Test t;
t = Test(5);
t = 5;
return 0;
}
编译竟然通过了,第17条和第18条语句竟然都是对的,竟然真的把普通类型转换成类类型,真的太不可思议的。当我们不写构造函数,编译通不过,但是当我们写了构造函数,编译竟然通过了,这是为什么?
3、再论构造函数
- 构造函数可以定义不同类型的参数
- 参数满足下列条件时称为转换构造函数
— 有且只有一个参数
— 参数是基本类型
— 参数是其它类类型
4、编译器的行为
- 旧式的C方式强制类型转换
int i;
Test t;
i = int(1.5);
t = Test(100);
- 编译器会尽量让源码通过编译
Test t;
t = 100;
100这个立即数默认为 int 类型,怎么可能赋值给 t 对象呢!现在就报错吗?不急,我看看有没有转换构造函数!OK,发现Test 类中定义了Test(int i),可以进行转换,默认等价于 t = Test(100)。
#include <iostream>
using namespace std;
class Test
{
private:
int i;
public:
Test(int i = 0)
{
this->i = i;
}
Test operator + (const Test& obj)
{
Test ret(i + obj.i);
return ret;
}
int getI()
{
return i;
}
};
int main()
{
Test t;
t = 5;
Test r;
r = t + 10;
cout << r.getI() << endl;
return 0;
}
如果第30行代码是手误加上了10,但是编译器却运行通过了,这样产生的Bug最难调试
编译器尽力尝试的结果是隐式类型转换,但是隐式类型转换会让程序以意想不到的方式进行工作,是工程中Bug的重要来源。
- 工程中通过 explicit 关键字杜绝编译器的转换尝试
- 转换构造函数被 explicit 修饰时只能进行显示转换
— 转换方式
1、static_cast<ClassName>(i);
2、ClassName(i);
3、(ClassName)value; //不推荐
#include <iostream>
using namespace std;
class Test
{
private:
int i;
public:
explicit Test(int i = 0)
{
this->i = i;
}
Test operator + (const Test& obj)
{
Test ret(i + obj.i);
return ret;
}
int getI()
{
return i;
}
};
int main()
{
Test t;
t = 5;
Test r;
r = t + 10;
cout << r.getI() << endl;
return 0;
}
在转换构造函数前加上 explicit,刚刚的程序就直接报错了,所有的隐式转换都不被认可,那我们全部转成显式转换,看看会不会输出结果。
#include <iostream>
using namespace std;
class Test
{
private:
int i;
public:
explicit Test(int i = 0)
{
this->i = i;
}
Test operator + (const Test& obj)
{
Test ret(i + obj.i);
return ret;
}
int getI()
{
return i;
}
};
int main()
{
Test t;
t = Test(5);
Test r;
r = t + Test(10);
cout << r.getI() << endl;
return 0;
}
当我们我们全部转成显式转换,程序就没有问题了。
在C++里面我们做好C++的强制类型转换:
#include <iostream>
using namespace std;
class Test
{
private:
int i;
public:
explicit Test(int i = 0)
{
this->i = i;
}
Test operator + (const Test& obj)
{
Test ret(i + obj.i);
return ret;
}
int getI()
{
return i;
}
};
int main()
{
Test t;
t = static_cast<Test>(5);
Test r;
r = t + static_cast<Test>(10);
cout << r.getI() << endl;
return 0;
}
— 转换方式
1、static_cast<ClassName>(i);
- 小结:
— 转换构造函数只有一个参数
— 转换构造函数的参数类型是其它类型
— 转换构造函数在类型转换时被调用
— 隐式类型转换是工程中Bug的重要来源
— explicit 关键字用于杜绝隐式类型转换
#include <iostream>
using namespace std;
class Value
{
};
class Test
{
private:
int i;
public:
Test(int i = 0)
{
this->i = i;
}
Test(Value v)
{
}
int getI()
{
return i;
}
Test operator+(const Test& obj)
{
Test ret;
ret.i = this->i + obj.i;
return ret;
}
};
int main()
{
Test t;
Value v;
t = v;
return 0;
}