第41课.类型转换函数(上)
1.再论类型转换
a.标准数据类型之间会进行隐士类型安全转换
b.转换规则
问题1:
eg:
#include <iostream>
#include <string>
using namespace std;
int main()
{
unsigned int ui = 1000;
int i = -2000;
cout << "i = " << i << endl;
cout << "ui = " << ui << endl;
cout << "ui + i = " << ui + i << endl; //注意这里不是-1000
return 0;
}
再次测试:
ui = -1000 很大的数
==> ==> 1000
i = 2000 2000
-------------------------------------------------
ui = 1000 1000
==> ==> 很大的数
i = -2000 很大的数
结论:
当unsigned int和int相加时
unsigned int + int = 负数: 输出采用类似于c语言中的**%u**
unsigned int + int = 正数: 输出采用类似于c语言中的**%d**
问题2
eg:
#include <iostream>
#include <string>
using namespace std;
int main()
{
short s = 'a';
cout << "sizeof(s + 'b') = " << sizeof(s + 'b') << endl;
return 0;
}
这里short + char理论上来说char应该隐式的转化为2字节的short,但是在实验中测试。两者都转换为了4字节的int,因为编译器这样做最高效。其他的就没有什么特殊的问题了。隐式转换没有什么问题。
2.再论构造函数(隐式转换的危害,基本类型->类类型)
a.构造函数可以定义不同类型的参数
b.参数满足下列条件时称为转换构造函数
1).有且仅有一个参数
2).参数是基本类型
3).参数是其它类类型
编译器的行为
编译器会通过转换构造函数,隐式的实现类型的转换。本来是用来构造对象的,结果被用来做隐式的类型转换,这是bug的一个重要来源。
解决办法:
a.工程中通过explicit关键字杜绝编译器的转换尝试
b.转换构造函数被explicit修饰时只能进行显示的类型转换
推荐的转换方式:
static_cast<ClassName>(Value);
eg:
#include <iostream>
#include <string>
using namespace std;
class Test
{
int mValue;
public:
Test ()
{
mValue = 0;
}
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;
#if 0
t = 5; // 5这个数默认类型为int, int怎么能赋值给t对象呢?编译器在这个时候,选择去查找转换构造函数。法想Test类中定义了Test (int i)这个转换构造函数。
//此时编译器将原语句转换为 Test = Test(5);这时Test(5)产生一个临时对象。
Test r;
r = t + 10; // t对象不能和int相加。此时调用隐式类型转换 t + Test(10);
// 这里就能看出bug了,本来是对象和对象的相加结果在这里对象和整形也能相加。
#endif
t = static_cast<Test>(5); //static_cast也可以用于基本能类型和类类型的转换
Test r;
r = t + static_cast<Test>(10);
cout << r.value() << endl;
return 0;
}