1.强制类型转换
- C方式的强制类型转换
- (Type) (Expression)
- Type (Expression)
#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;
}
- C方式强制类型转换存在的问题
- 过于粗暴:任意类型之间都可以进行转换,编译器很难判断其正确性
- 难于定位 :在源码中无法快速定位所有使用强制类型转换的语句
- 强制类型转换在实际工程中是很难完全避免的!如何进行更加安全可靠的转换?
2.新式类型转换
- C++将强制类型转换分为4种不同的类型
- type:是要转换的目标类型;expression:要转换的值
2.1 static_cast强制类型转换
- 用于基本类型间的转换 ,不能用于基本类型指针间的转换
- 用于有继承关系类对象之间的转换和类指针之间的转换
#include <stdio.h>
int main()
{
int i = 0x12345;
char c = 'c';
int *pi = &i;
char *pc = &c;
c = static_cast<char>(i); // static_cast用于基本类型间的转换,但不能用于基本类型指针间的转换
pc = static_cast<char *>(pi); // error,不能用于基本类型指针之间的转换
printf("Press any key to continue...");
getchar();
return 0;
}
2.2 const_cast强制类型转换
- 用于去除变量的只读属性,强制转换的目标类型必须是指针或引用
#include <stdio.h>
int main()
{
const int &j = 1;
int &k = const_cast<int &>(j); // 将只读变量j降级为普通变量
const int x = 2;
int &y = const_cast<int &>(x); // y时x常量地址的别名
k = 5;
printf("k = %d\n", k);
printf("j = %d\n", j);
y = 8;
printf("x = %d\n", x); // 从符号表中直接取出2
printf("y = %d\n", y);
printf("&x = %p\n", &x);
printf("&y = %p\n", &y);
printf("Press any key to continue...");
getchar();
return 0;
}
- 运行结果
2.3 reinterpret_cast强制类型转换
- 用于指针类型间的强制转换
- 用于整数和指针类型间的强制转换
#include <stdio.h>
int main()
{
int i = 0;
char c = 'c';
int *pi = &i;
char *pc = &c;
pc = reinterpret_cast<char *>(pi);
pi = reinterpret_cast<int *>(pc);
// c = reinterpret_cast<char>(i); // Oops!
printf("Press any key to continue...");
getchar();
return 0;
}
2.4 dynamic_cast强制类型转换
- 用于有继承关系的类指针间的转换
- 用于有交叉关系的类指针间的转换
- 具有类型检查的功能
- 需要虚函数的支持
3.关于继承中的强制类型转换
- 继承中如何正确的使用强制类型转换?
- dynamic_cast是与继承相关的类型转换关键字
- dynamic_cast要求相关的类中必须有虚函数
- 用于有直接或者间接继承关系的指针(引用)之间
- 指针:转换成功:得到目标类型的指针; 转换失败:得到一个空指针
- 引用: 转换成功:得到目标类型的引用 ;转换失败:得到一个异常操作信息
- 编译器会检查dynamic_cast的使用是否正确
- 类型转换的结果只可能在运行阶段才能得到
#include <iostream>
using namespace std;
class Base
{
public:
Base()
{
cout << "Base::Base()" << endl;
}
virtual ~Base()
{
cout << "Base::~Base()" << endl;
}
};
class Derived : public Base
{
};
int main()
{
Base *p = new Base;
Derived *pd = dynamic_cast<Derived*>(p); //编译成功,转换失败返回0
if( pd != NULL )
{
cout << "pd = " << pd << endl;
}
else
{
cout << "Cast error!" << endl;
}
Base* p1 = new Derived();
Derived* pd1 = dynamic_cast<Derived*>(p1);//转换成功
if( pd1 != NULL )
{
cout << "pd1 = " << pd1 << endl;
}
else
{
cout << "Cast error!" << endl;
}
delete p;
delete p1;
return 0;
}
- 运行结果
4.小结
- C方式的强制类型转换
- 过于粗暴
- 潜在的问题不易被发现
- 不易在代码中定位
- 新式类型转换以C++关键字的方式出现
- 编译器能够帮助检查潜在的问题
- 非常方便的在代码中定位
- 支持动态类型识别(dynamic_cast)
- dynamic_cast是与继承相关的专用转换关键字