强制类型转换在有些地方起到了很大的作用,在看C++中的强制类型转换时,我们首先看一下我们熟悉的C语言中的强制类型转换。
一.C语言的强制类型转换
C语言中强制类型转换分为两种:
隐式类型转换(相似类型转换,及相关类型的转换,这里和类型提升也优点相似)
显示类型转换(不相关类型之间的转换,比如指针和整型)
int main()
{
int i = 1;
double b = i;//隐式类型转换
printf("%d,%2fd\n", i, b);
int* p = &i;
int num = (int)p;//显示类型转换
printf("%x,%d\n", p, num);
system("pause");
return 0;
}
我们看到C语言中的两种强制类型转换,其中的隐式类型转换存在很大的弊端,比如:数组中在任意位置插入,需要将元素向后搬移,这就有可能产生错误,这里就不做代码演示了。感兴趣的同学可以留言,我会贴出来。而且C语言的强制类型转换我们可以看到不够规范,这使得代码的可读性降低了很大。
二.C++的强制类型转换
1.static_cast:用于非多态类型转换(静态转换),任何标准转换都可以用它,但是不能用于两个不相关的类型转换。
int i = 10;
double b = static_cast<double>(i);
cout << i << " " << b << endl;
2.reinterpret_cast:将一种类型转换为另一种不同的类型。
int i = 10;
int* b = reinterpret_cast<int*>(i);
cout << i << " " << b << endl;
3.const_cast:删除变量const的属性,方便赋值
1.)在看这个强制类型转换之前,我们首先看一下C语言中一个有趣的事情。
int main()
{
const int i = 3;
int* p = (int*)&i;
*p = 4;
printf("%d\n", i);
system("pause");
return 0;
}
我们首先看一下,该程序会输出什么勒????可能很多同学会认为是输出4,其实不然。其实是3.我们来看以下编译器迷惑的地方。
我们打开监视窗口发现,明明是4,为什么输出的是3勒,这个看起来就有点扯了。我们在打开汇编代码看一下。
我们看到函数在调用堆栈的时候,push进去的是3,那么在pop出栈的时候肯定也是3.这就相当于将i这个值放在了寄存器上,并不是内存上。因为程序在优化的时候,如果一个变量使用频率非出高,那么这个变量有可能就会被优化为,只向寄存器加载一次,往后直接使用寄存器中保存的值,而不关心这个变量内存里边的值,因此就有可能造成程序的逻辑上的一些错误
问题:那么如何让他的输出和我们刚开预想的一样输出为3勒??
我们只需要将定义的数据前面加上volatile关键字,这样就可以改变他的值
volatile关键字解析
作用:保持内存可见性(CPU每次处理这个被volatile修饰的变量的时候,都会从内存中重新加载变量的值到寄存器)
这里就不做加了volatile的代码了,有兴趣的可以自行去写。
2.)C++中的const_cast
const int i = 3;
int* p = const_cast<int*>(&i);
*p = 3;
cout << p << " " << i << endl;
4.dynamic_cast:用于将一个父类对象的指针转换为子类对象的指针或引用。(动态交换)
向上转型:子类对象指针-->父类对象指针/引用(不需要转化)
向下转型:父类对象指针-->子类对象指针/引用(用dynamic_cast转型是安全的)
注意:
dynam_cast:只能用于有虚函数的类(必须有共有继承和虚函数)
dynam_cast:会先检查能否转型成功,能成功则转型,不能成功则返回0
class A
{
public:
virtual void show()
{
cout << "ambition" << endl;
}
int a;
private:
};
class B:public A
{
public:
int b;
private:
};
void Func(A* a)
{
B* b = dynamic_cast<B*>(a);
if (b != NULL)
{
b->a = 20;
b->b = 10;
}
else
{
b->a = 30;
}
}