分别是: static_cast、dynamic_cast、reinterpret_cast、const_cast, 这4个被C++内置为关键字。
在C++标准库中,还扩展几大转换:
static_pointer_cast、dynamic_pointer_cast、reinterpret_cast、const_pointer_cast用于引用计数指针的转换,可以了解一下。
渊源
首先我们来说说,这几种转换的来源,或者为什么为这几个转换,当然这是C++扩展C时,必须要有几大转换。
在C语言中,只有一种强转,如下:
1
2
3
4
5
6
7
|
double b = 1.2; int a = b; // <==> int a = (int) b; // 又或者一些指针的转换: char * t = ( char *) malloc (4); |
由于C是弱类型语言,类型都是平凡类型(POD类型),所以转换,就仅仅只是一个类型上的转换。而C升级到C++的时候
增加了很多的特性,类、const关键字等等东西,在C中的指针或者结构体的转换,都是不改变内容的情况进行类型转换,
亦或者截断内容转换,像指针的转换,转换之后,除了类型,指向的地址是不会更改。
而C++中增加了类的概念,在对类对象或者指针进行强转时,C中强转就不够用了,比如:
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
|
// 例1: class A { public : A() { qDebug() << ( void *) this ; } }; class B { public : B() { qDebug() << ( void *) this ; } }; class C : public A, public B { public : C() { qDebug() << ( void *) this ; } }; C* c = new C; B* b = c; //b的指针地址比C的指针地址要大1, 这是指针偏移的概念。 // 如果有虚函数,指针偏移则会更大。 // 例如2: class A { public : virtual void func() { } }; class B : public A { public : virtual void func() { } }; B b; A a = b; //此时a中的虚函数表的地址,是类a的虚函数表地址,b的则是b的, // 也就是说,在强转的过程中,内容发生变化。 |
因此在C++中类的强转,发生了一些微妙上的变化,于是就有static_cast和reinterpret_cast,而原本C中强制类型转换,在
C++中我们仍然习惯称为强转,它实际上默认是静态类型转换,也就是C++的以下的转换是等价的:
1
2
3
4
5
6
7
8
9
|
double b = 3.1; int a = b; // <==> a = static_cast<int>(b); C* c = new C; B* b = c; // <==> B* b = static_cast<B*>(c); |
显然这种强转和C的强转不是一码事,至少在C中指针转换,指针指向的内容是不会变的,而在C++中为了保证安全,强转
它可能会导致内容发生改变, 于是C++为了保留原有强转的概念,增加reinterpret_cast这个关键字,它称为C++的强制类型
转换。
总结一下: C++在扩展C的过程中,虽然保留了C的强制转换的写法,但是为了安全,与C的强转有区别,因此C中的强转就是
静态类型转换,并增加reinterpret_cast保留类C强转的功能。
至于dynamic_cast, 在虚函数多态那一篇详细做了说明,但这里仍需要说明一点,为啥dynamic_cast和static_cast一个为静态、
一个为动态。(reinterpret_castC++的强制类型转换,因为不安全,所以并不常用)。
在C中用的更多的是static_cast和dynamic_cast, 同它们的名字一样,静态转换,是在编译期就已经决定好如何进行转换(如何指针偏移,
如何进行内容修改),运行按照规则转换就好,而动态类型转换,纯粹发生在运行期,靠的虚函数表,简单的说,静态类型转换不需要
依赖运行时的内容,而动态类型,则是需要依赖运行时的内容的。
最后就是const_cast, 这玩意纯粹是因为C++增加了const关键字,这个关键字就是欺骗编译期的东西,为的是增加代码的安全性、规范性和可读性。
尽量不要用,功能也非常简单,去除变量const修饰。
评论(0)