C++强制类型转换

C++强制类型转换

在前面C语言的学习中我们知道C语言有隐式类型转换与强制类型转换,比如当我们用一个int类型的值加一个double类型的值的时候编译器会默认将double转换成为int类型,这个就是C语言中的隐式类型转换。同样的一个void类型的指针我们用(int)也可以将他强制转换成int*类型,这个是C语言中强制类型转换。
在C++中我们也有一套强制类型转换,他们分别是static_cast/reinterpret_cast/const_cast/dynamic_cast
可是我们C语言的类型转换用习惯了为什么要改用,C++风格的强制类型转换,它的好处在于可以更清晰的表达我们要干什么。并且C++的强制类型转换支持动态转换

static_cast

首先我们来看第一中强制类型转换,这一种用于非多态类型的转换(静态转换)任何标准转换都可以用它,但是只能用于相关类型之间转换。比如int与double类型等

int a;
double b = static_cast(a);

用法如上,将static_cast当作一个类型进行使用即可。一般来说,如果编译器发现一个的算术类型试图赋值给较小的类型,就会给出警告信息;但是当我们执行了显式的类型转换后,警告信息就会被关闭了。

reinterpret_cast

这一种强制类型转换是一种很bug的操作,他和static_cast的功能相当于C语言中隐式类型转换的功能。理论上它允许任何类型的转换,可以是任意的不相关类型。甚至可以是我们的自定义类型。由于它的自由度太高了所以我们用它的时候一定要考虑安全问题,不到万不得已不能使用。
下面演示一下用法。

typedef void(*FUNC)();
int fun(int i)
{
 cout << "hahah" << endl;
 return 0;
}
int main()
{
 FUNC f = reinterpret_cast(fun);
 system("pause");
 return 0;
}

不到万不得已的时候不适用这一种强制类型转换。

const_cast

const_cast最常用的用途就是删除变量的const属性,方便赋值。
一旦我们用这种强制类型转换去掉了const属性那么编译器就允许我们对其进行写操作了。当我们操作的对象不是一个常量的时候,使用强制类型转化也是合法行为。

const int a = 2;
 int* p = const_cast(&a);
 *p = 3;
 cout << a << endl;
 system("pause");
 return 0;

我们来看这一段代码,按照刚刚说的去掉a的const熟悉再通过指针赋值3,应该输出的是3
在这里插入图片描述
可是最后的结果是2,我们再通过调试窗口来看看
在这里插入图片描述
调试窗口说明我们的结果没有问题,那么为什么会有这种情况呢?
当我们把a用const修饰的时候编译器以为我们不会改变了,所以将他直接放到了缓冲区,这里算是编译器的一个优化,可是后面我们用强制类型转换改变了a的值所以导致终端从缓冲区中读到的值是2,而我们实际的值是3.
这里我们要用到volatile关键字声明a,这个关键字是保持内存的可见性,防止编译器优化而是老老实实的去内存读取。

dynamic_cast

dynamic_cast用于将一个父类对象的指针转换为子类对象的指针或引用,也就是动态转换。这个强制类型转换就体现出C语言与C++的区别了,前三种强制类型转换C语言也可以做到,可是这一种强制类型转换只有C++可以做到。
dynamic_cast分为向上转型与向下转型
向上转型就是将子类对象指针转化为父类对象指针或引用,其实根本不需要转换,系统会直接切片
向下转型就是父类对象指针转化为子类对象指针或引用,相比const_cast来说dynamic_cast更加安全,因为dynamic_cast会先进行检查能否转化成功,能成功就转化,否则就返回0.
如果被转换的指针不是一个被请求的有效完整的对象指针,返回值为NULL. 对于引用 类型,会抛出bad_cast异常

class A
{
public:
 virtual void fun()
 {}
};
class B :public A
{
 virtual void fun()
 {}
};
int main()
{
 A* a = new A;
 B* b = new B;
 B* p = dynamic_cast(a);
 system("pause");
 return 0;
}

你可能感兴趣的:(C++基础)