C++强制类型转换

来源:互联网 发布:数据访问框架 编辑:程序博客网 时间:2024/05/14 10:49

先后看过几次关于C++类型转换的资料,甚至还用过几次,可对其了解还是很模糊,本次特别予以总结。不是随便写的,真的是用心写的,姑且看吧。

C++命名的强制类型转换也称作新式类型转换,也是C语言类型转换的一个演进。

看一个C语言的类型转换:

1char *hopeItWorks = (char *)0x00ff0000;

《C++必知必会》一书把该种类型转换描述成“龌龊”,因为这种类型转换相对于C++的类型转换来说力度要大,大到有时你并不清楚具体发生了哪些转换,即有可能转换即使超出了你的期望而没有任何提醒,最终导致程序运行失败。个人观点,该书作者(译者)描述太过于夸张了,C语言是个奔放的语言,其设计理念之一就是:程序员清楚自已在做什么。

 

C++的类型转换其实把C语言类型转换细分了一下,一分为四。(当然,同时兼容老式类型转换)

1、const_cast

该操作符允许添加或移除表达式中类型的const或volatile修饰符:
1const Person *getEmployee()
2{
3    // do some thing and return const Person *
4}
5Person *anEmployee = const_cast<Person *>(getEmployee()); // C++类型转换
6Person *anEmployee = (Person *)getEmployee();// C类型转换

上面给出两种类型转换,都是去掉函数所返回指针的const属性,表面上看是一样的,但是如果函数发生改变后,就能看出这两种转换的差异:
1const Employee *getEmployee() // 返回类型变了
2{
3    // do some thing and return const Employee *
4}
5Person *anEmployee = const_cast<Person *>(getEmployee()); // C++类型转换,编译提示错误
6Person *anEmployee = (Person *)getEmployee();// C类型转换,编译不提示错误

这里函数返回类型发生改变,在const_cast试图将const Employee * 转换为Employee *时就已经超出了其能力范围,会在编译阶段给出提示,这往往是很有用的,当然,C++可以做到能力更强的类型转换,且向下看。

 

2、static_cast

编译器隐式执行的任何类型转换都可以由static_cast显式完成:
1double d = 97.0
2char ch = static_cast<char>d;//没有编译告警

对于从一个较大的算式类型到一个较小类型的赋值,编译器通常产生警告,当我们显式地提供强制类型转换时,警告信息就会关闭。此种类型转换告诉编译器:我想要一个静静的(static)转换,你懂的,请闭嘴。
静态转换常用于基类的指针或引用,转型为一个派生类的指针为引用。
需要注意的是这不是一个非常安全的转换,损失的精度需要程序员去考虑。使用此转换的一个考虑是:可跨平台移植。

3、reinterpret_cast

顾名思义,重新解释。它从位(bit)的角度来看待一个对象,从而允许将一个东西看作另一个完全不同的东西:
1char *hopeItWorks = reinterpret_cast<char *>(0x00ff0000); // 把int假装成指针
2int *hopeless = reinterpret_cast<int *>(hopeItWorks);//把char *假装成int *

这是个非常危险的转换,在C++类型转换里面威力也最大,非常容易出错。举个例子,一本横向排版的书,硬是按照竖向排版的方式进行解读,一般是读不出合理的内容。
给出一种几乎是错误的转换:
1int *ip;
2char *pc = reinterpret_cast<char *>(ip);
3std::string str(pc); // 使用pc初始化一个string 对象,很可能出现运行时错误


4、dynamic_cast

顾名思义,动态的转换。大家知道,C++是具有多态特性的,该种转换仅用于对多态类型进行向下转型(也就是说,被转型的表达式的类型,必须是一个指向带有虚函数的类类型的指针)。上面讲的static_cast也可以从基类指换到派生类,但是不安全的。dynamic_cast执行运行期检查工作,来判定转型的正常性,当然是要会出代价的,好比,多态性也会带来性能开销一样。
01const Shape *getNextShape()
02{
03    // do some thing and return const Shape *
04}
05const Circle *cp = dynamic_cast<const Circle *>(getNextShape());
06if(cp)
07{
08    ...
09}
10注: Circle类派生于Shape类。


至此,C++四种转换都讲完了。总结一下,C++类型转换其实是对C语言类型转换的细分及扩充(扩充类类型之间的转换)。

《C++Primer》中有一句特别好:强制类型转换关闭或挂起了正常的类型检查。强烈建议程序员避免使用强制类型转换,不依赖强制类型转换也能写出很好的C++程序。

原创粉丝点击