1.C方式的强制类型转换存在的问题
过于粗暴:任何类型之间都可以进行转换,编译器很难判断其正确性。
难于定位:在源码中无法快速定位所以使用强制类型转换的语句。
隐式类型的转换和强制转换
所谓的隐式类型的强转就是相近的类型的转化,强制转换就是讲类型
如下:
int main()
{
int i = 1;
double j = i;
printf("%d,%2f\n", i, j); //隐式
int *p = &i;
int address = (int)p://强转
printf("%x,%d\n",p,address);
system("pause");
return 0;
}
2.C++新增的4种不同类型的强制类型转换。
static_cast强制类型转换:int转flaot,double转int等等。
-> 用于基本类型间的转换。
-> 不能用于基本类型指针间的转换。
-> 用于有继承关系类对象之间的转换和类指针之间的转换。
void Tes1()
{
int i = 2;
double j = static_cast<double>(i);
printf("%d,%2f\n", i,j);
}
const_cast强制类型转换:去常性
-> 用于去除变量的只读属性。
-> 强制转换的目标类型必须是指针或引用。
void Test3()
{
const int a = 2;
int *p = const_cast<int *>(&a);
*p = 3;
printf("%d", a);
}
reinterpret_cast强制类型转换:
-> 用于指针类型间的强制转换。
-> 用于整数和指针类型间的强制转换。
void Test2()
{
int i = 10;
int *j = &i;
int address = reinterpret_cast<int>(j);
printf("%d,%d", i, j);
}
dynamic_cast强制类型转换:
-> 用于有继承关系的类指针间的转换。
-> 用于有交叉关系的类指针间的转换。
-> 具有类型检查的功能。
-> 需要虚函数的支持。
【作用】:将一个基类对象指针(或引用)cast到继承类指针,dynamic_cast会根据基类指针是否真正指向继承类指针来做相应处理, 即会作出一定的判断。
若对指针进行dynamic_cast,失败返回null,成功返回正常cast后的对象指针;
若对引用进行dynamic_cast,失败抛出一个异常,成功返回正常cast后的对象引用。
【注意】:
1、dynamic_cast在将父类cast到子类时,父类必须要有虚函数,否则编译器会报错。
2、 dynamic_cast主要用于类层次间的上行转换和下行转换,还可以用于类之间的交叉转换。
在类层次间进行上行转换时,dynamic_cast和static_cast的效果是一样的;
在进行下行转换时,dynamic_cast具有类型检查的功能,比static_cast更安全。
下面通过一个简单的例子来说明dynamic_cast的作用:
#include <iostream>
#include <assert.h>
using namespace std;
// 我是父类
class Tfather
{
public:
virtual void f() { cout << "father's f()" << endl; }
};
// 我是子类
class Tson : public Tfather
{
public:
void f() { cout << "son's f()" << endl; }
int data; // 我是子类独有成员
};
int main()
{
Tfather father;
Tson son;
son.data = 123;
Tfather *pf;
Tson *ps;
/* 上行转换:没有问题,多态有效 */
ps = &son;
pf = dynamic_cast<Tfather *>(ps);
pf->f();
/* 下行转换(pf实际指向子类对象):没有问题 */
pf = &son;
ps = dynamic_cast<Tson *>(pf);
ps->f();
cout << ps->data << endl; // 访问子类独有成员有效
/* 下行转换(pf实际指向父类对象):含有不安全操作,dynamic_cast发挥作用返回NULL */
pf = &father;
ps = dynamic_cast<Tson *>(pf);
assert(ps != NULL); // 违背断言,阻止以下不安全操作
ps->f();
cout << ps->data << endl; // 不安全操作,对象实例根本没有data成员
/* 下行转换(pf实际指向父类对象):含有不安全操作,static_cast无视 */
pf = &father;
ps = static_cast<Tson *>(pf);
assert(ps != NULL);
ps->f();
cout << ps->data << endl; // 不安全操作,对象实例根本没有data成员
system("pause");
}
小结:
C方式的强制类型转换:
-> 过于粗暴,潜在的问题不易被发现,不易在代码中定位。
新式类型转换以C++关键字的方式出现:
-> 编译器能够帮助检查潜在的问题。
-> 非常方便的在代码中定位。
-> 支持动态类型识别。