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)