类型转换

C语言的类型转换

  • 隐式类型转换:double f = 1/2;中,虽然用double变量来接收结果,但表达式运算全是整型数,会转换为整形数的除法,运算结果为0,转换为double后为0.0;double f = 1.0/2;中,由于1.0是浮点型,所以2会发生隐式类型转换变为2.0,最终结果是0.5;
  • 显示类型转换:(类型说明符)(表达式),比如double f = double(1)/double(2);

  

C语言的类型转换很灵活,但存在一些问题:

  1. 任意类型之间都可以转换,编译器无法判断其准确性;
  2. 难于定位,在源码中无法快速定位转换位置;

C++的类型转换

const_case

  用于转换指针或引用,去掉类型的const属性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//const_case使用

int main()
{
// C++ const_cast
const int a = 10;
//int* pA = &a; //const int*类型不能用于初始化int*类型实体
int* pA = const_cast<int*>(&a);
*pA = 100;

//需要注意,虽然我们用指针把a的值改变了,实际上也确实改变了
//但假如我们要使用a的值,比如cout一下,那么a原来的值(10)会直接赋值到行为上
//cout<<a<<endl;输出的结果是10,而不是100
return 0;
}

reinterpret_cast

  这是一种很危险的类型转换。既不检查指向的内容,也不检查指针类型本身,只是做了类型的重新解释。reinterpret_cast需要保证转换前后的类型所占用的内存大小一致,否则将引发编译时错误。

  虽然危险,但工程中的使用常见还是比较广泛,比如void*和其他类型的转换,遇到这种场景最好使用reinterpret_cast而不是C语言的强制类型转换,因为C语言的强制转换不做任何的检查。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//reinterpret_cast使用

int Test()
{
return 0;
}

int main()
{
// C++ reinterpret_cast
typedef void(*FuncPtr) (); //定义函数指针,返回值void,参数也是void

FuncPtr funcPtr;
//funcPtr = &Test; //两个函数模型不匹配,不能赋值
funcPtr = reinterpret_cast<FuncPtr>(&Test);

return 0;
}

static_case和dynamic_cast

  用于基本的类型转换(这种方式就是类似于C语言的类型转换方式)。也可以用于有继承关系类对象和类指针之间的转换,但需要由程序员来确保转换是安全的,它不会产生动态转换的类型安全检查的开销,因为类型检查不是编译器能检测出来的,必须要等到运行时才能动态检查。

  dynamic_cast是为了弥补static_cast的不足,可以做类型的检查。它只能用于含有虚函数的类,必须用于多态体系中,用于类层次间的向上和向下转化;向下转化时,如果是非法的对于指针返回NULL。(向上转化:子类转换为父类;向下转化:父类转化为子类。子类转化为父类比较安全,但父类转化为子类不安全,因为子类一定有父类的属性,但父类未必有子类的属性)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
//static_cast 和 dynamic_cast

class Base
{
public:
Base() : _i(0) { ; }
virtual void T() { cout << "Base:T" << _i << endl; } //必须有虚函数,dynamic_cast才做检查
private:
int _i;
};

class Derived : public Base
{
public:
Derived() :_j(1) { ; }
virtual void T() { cout << "Derived:T" << _j << endl; }

private:
int _j;
};

int main()
{
// static_cast
int i = 6;
double d = static_cast<double>(i); //基本类型转换 int -> double
double d2 = 5.6;
int i2 = static_cast<int>(d2); //基本类型转换 double -> int

int ii = 5;
double dd = static_cast<double>(ii);
double dd2 = 5.6;
int ii2 = static_cast<int>(dd2);

// static_cast与dynamic_cast

Base cb;
Derived cd;
Base* pcb;
Derived* pcd;

// 子类--》 父类
// 这个是安全的
pcb = static_cast<Base*>(&cd);
if (pcb == NULL)
{
cout << "unsafe static_cast from Derived to Base" << endl;
}
pcb = dynamic_cast<Base*>(&cd);
if (pcb == NULL)
{
cout << "unsafe dynamic_cast from Derived to Base" << endl;
}

// 父类--》 子类
// 这个有风险,dynamic_cast会做检查导致失败
pcd = static_cast<Derived*>(&cb);
if (pcd == NULL)
{
cout << "unsafe static_cast from Base to Derived" << endl;
}
pcd = dynamic_cast<Derived*>(&cb);
if (pcd== NULL)
{
cout << "unsafe dynamic_cast from Base to Derived" << endl;
}

return 0;
}