C++新特性(二)更安全的强制类型转换


C语言原来有简单的语法实现强制类型转换,为什么C++还要确定新特性实现强制类型转换呢?归根到底是因为C语言强制类型转换有以下三个缺点。
1,没有从形式上体现转换功能和风险的不同。
例如,将int强制转换成double是没有风险的,而将常量指针转换成非常量指针,将基类指针转换成派生类指针都是高风险的,而且后两者带来的风险不同(即可能引发不同种类的错误) , C语言的强制类型转换形式对这些不同并不加以区分。
2,将多态基类指针转换成派生类指针时不检查安全性,即无法判断转换后的指针是否确实指向一个派生类对象。
3,难以在程序中寻找到底什么地方进行了强制类型转换。——强制类型转换可能是引发程序运行时错误的一个原因,因此在程序出错时,可能就会想到是不是有哪些强制类型转换出了问题。举个例子

int n=1;
int *p=(int*)n;
*p=9;//运行时才出现错误,因为地址为1的内存不能使用(一般是操作系统占用的)

1,const_cast

const_cast用于去除指针,引用,this指针的const属性。

//1,指针类型
const int n=5;
int n1=const_cast<int>(n);//编译错误,const_cast中的类型必须是指针,引用,或this指针。
int *p=const_cast<int*>(&n);//正确
*p=10;//可修改n的值了
//2,引用类型
const int &a=const_cast<int&>(n);
a=9;//可修改n的值了。
//3,this指针
//前面已经介绍过,在类里面可以有一种函数叫常成员函数,这个函数内部的成员变量不可被修改,原因是
//这个成员函数内部this指针为const 类*const this,另外再回忆以下,前面的const表示不可修改
//this指向的内容,后面const表示不可修改this本身的值。*const thiss=const_cast<* connst>(this)//转换以后,thiss就和普通成员函数中的this指针一样了

2,static_cast

static_cast基本等价于隐式转换的一种类型转换运算符。 可使用于需要明确显式转换的地方。
可以用于低风险的转换。
1,整型和浮点型
2,字符与整形.
3,转换运算符
4,基类与派生类之间的转换(子类转父类)

//什么是转换运算符?有的类内部提供了一种转换运算符的方式,让外界将这个类当作特定类型使用
class CInt{
public:
    operator int()
    {  return m_nInt;}
    int m_nInt;
}
CInt obj;
int k=static_cast<int> (obj);

4,空指针转换为任何目标类型的指针
不可以用与风险较高的转换
1,不同类型的指针之间互相转换
2,整型和指针之间的互相转换
3,不同类型的引用之间的转换
5,子类与派生类之间的转换(父类转子类)
注意,使用static_cast关键字可以实现父类转子类编译器不报错,但本质上他仍然是不安全的,除非该父类对象指针本来就是子类对象指针转换过去的,现在再用static_cast关键字转换回来就没有问题。

3,dynamic_cast

dynamic_cast用于具有虚函数的基类与派生类之间的指针或引用的转换。这句话读起来很拗口,建议多读几遍体会一下意思。
使用dynamic_cast的条件:
1,基类必须具备虚函数
原因: dynamic_ cast是运行时类型检查,需要运行时类型信息(RTTI),而这个信息是存储与类的虚函数表关系紧密,只有一个类定义了虚函数,才会有虚函数表。
2,运行时检查,转型不成功则返回一个空指针
3,非必要不要使用dynamic. cast,有额外的函数开销
常见的转换方式:
1,基类指针或引用转派生类指针(必须使用dynamic cast)
2,派生类指针或引用转基类指针(可以使用dynamic_cast,但是更推荐使用static
cast)
实践:
假设有一个存在虚函数成员的父类Cfather,子类Cson。并且子类有一个父类没有的成员变量 int m_test;看以下操作:

Cfather* pfather=new Cfather;
Cson* pson=new Cson;
pson=dynamic_cast<Cson*>(pfather);//向下转换,父类转子类,不安全,运行时通过RTTI检测出不能完全转换,pson直接返回空指针。
//当然,如果这里的pfather本来就是子类对象,返回值就没问题。
pfather=static_cast<Cfather*>(pson);//向上转换,子类转父类,安全,可以用dynamic_cast,但更推荐使用static_cast

最后记住,dynamic_cast能够在运行的时刻,检测出被转换的指针的类型(依赖RTTI),有额外的开销,一般只有在父类有虚函数时,向下转换的时候必须使用。
使用dynamic_cast时要在项目属性页配置下面选项为“是”,不过一般不用手动配置,默认选项就是“是”
在这里插入图片描述

4,reinterpret_cast

该转换比较简单,就相当于C语言的强制类型转换,reinterpret_cast不过是显式说明了该强制类型转换了而已。


版权声明:本文为weixin_42445051原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。