第11课 新型的类型转换
1. C方式的强制类型转换
(1)强制类型转换形式
①(Type)(Expression)
②Type(Expression) //老式的
【编程实验】粗暴的类型转换 11-1.cpp
#include <stdio.h> typedef void PF(int); struct Point { int x; int y; }; int main() { int v = 0x12345; PF* pf = (PF*)v; char c = char(v);//老式写法,很像函数调用 Point* p = (Point*)v; pf(5); printf("p->x = %d\n", p->x); printf("p->y = %d\n", p->y); return 0; }
运行结果:
(2)强制类型转换存在的问题
①过于粗暴:任意类型之间都可以进行转换,编译器很难判断其正确性
②难于定位:在源码中无法快速定位所有使用强制类型转换的语句
2. C++中新式的4种强制类型转换
(1)用法:xxx_cast(Type)(Expression)
(2)4种类型
类型 |
适用范围 |
举例 |
备注 |
static_cast |
①用于基本类型之间的转换 ②不能用于基本类型的指针间的转换 ③类与子类对象之间的转换或类指针间转换 |
int i = 0; char c = 'A';
int* pi = &i; char* pc = &c;
c = static_cast<char>(i); //ok
//不能用于基本类型的指针间转换 pc = static_cast<char*>(pi);//oops |
①编译时检查,可用于非多态类指针间的转换,但不支持交叉转换。 ②在类层次间进行转换时,上行转换static_cast与dynamic_cast效果是一样的,但下行转换时dynamic_cast具有类型检查功能,比static_cast更安全。 |
const_cast |
目标类型(即尖括号内的类型)必须是指针或引用 |
//i有内存,因别名,每次从内存读取i const int& i = 1;//i为引用 int& a = const_cast<int&>(i);
const int j = 1; //为j分配内存,但不会去用它,从符号表中取j int& b = const_cast<int&>(j);
a = 5; //i==5;a==5; b = 3; //j==1,b==3; |
用于去除变量的const属性 |
reinterpret_cast |
①用于指针类型间的强制转换 ②用于整数和指针类型之间的强制转换 |
typedef void PF(int);
int i = 0; char c = 'c';
int* pi = reinterpret_cast<int*>(&c); char*pc = reinterpret_cast<char*>(&i);
PF*pf= reinterpret_cast<PF*>(0x12345678);
//以下错,要用static_cast c = reinterpret_cast<char>(i); |
reinterpret_cast直接从二进制位进行复制,是一种极其不安全的转换。 |
dynamic_cast |
①用于有继承关系的类指针间。 ②用于有交叉关系的类指针之间(如,继承于同一父类的两个子类间的转换)
|
详见后面章节的分析 |
①dynamic_cast具有类型检查的功能。 ②运行时检查,用于多态的类型转换(上转,下转和交叉转换),只能转换指针和引用且需要虚函数的支持,才不会报错。而static_cast转换,即使基类没有虚函数,编译也不会报错,但这种转换不完全。 ③dynamic_cast支持交叉转换,而satic_cast不支持这种转换 |
【实例分析】新式类型转化初探 11-2.cpp
#include <stdio.h> void static_cast_demo() { int i = 0x12345; char c = 'c'; int* pi = &i; char* pc = &c; c = static_cast<char>(i);//基本类型 //基本类型的指针间,非法 //pc = static_cast<char*>(pi); } void const_cast_demo() { //用常量初始化引用,要分配内存。故j为变量,因加const而成只读变量 const int& j = 1;//j为引用--》只读变量,说明j不能做为左值而己 int& k = const_cast<int&>(j); //转为普通引用,k就是j的别名 k = 5; printf("k = %d\n", k); //5 printf("j = %d\n", j); //5 const int x = 2; //x为常量 int& y = const_cast<int&>(x);//此时,会为x分配内存 //int z = const_cast<int>(x); //oops,目标类型只能是引用或指针 y = 3; printf("x = %d\n", x); //2 printf("y = %d\n", y); //3 printf("&x = %d\n", &x); printf("&y = %d\n", &y); //x与y的内存地址是相同的 } void reinterpret_cast_demo() { int i = 0; char c = 'c'; int* pi = &i; char* pc = &c; pc = reinterpret_cast<char*>(pi); //ok,指针间 pi = reinterpret_cast<int*>(pc); //ok,指针间 pi = reinterpret_cast<int*>(i); //ok,整数与指针间 //c = reinterpret_cast<char>(i); //oops,基本类型间转换,要用static_cast } void dynamic_cast_demo() { int i = 0; int* pi = &i; //char* pc = dynamic_cast<char*>(pi); //oops,目标类型应为类的指针或引用 } int main() { static_cast_demo(); const_cast_demo(); reinterpret_cast_demo(); dynamic_cast_demo(); return 0; }
运行结果:
3. 小结
(1)C方式的强制类型转换
-
①过于粗暴;
-
②潜在的问题不易被发现;
-
③不易在代码中定位
(2)新式类型转换以C++关键字的方式出现
-
①编译器能够帮助检查潜在的问题
-
②非常方便的在代码中定位
-
③支持动态类型识别(dynamic_cast)