类型转换是一种机制,让程序员能够暂时或永久性改变编译器对对象的解释。注意,这并不意味着程序员改变了对象本身,而只是改变了对对象的解释

在很多情况下,类型转换是合理的需求,可解决重要的兼容问题。因此,程序员经常需要让编译器按其所需的方式解释数据,让应用程序能够成功编译并执行。

C++编译器仍需向后兼容以确保遗留代码能够通过编译,因此支持下面这样的语法:int* pBuf = (int *)pString ;

C风格类型转换实际上强迫编译器根据程序员的选择来解释目标对象,强迫编译器遵从自己的意愿。然而,对不希望类型转换破坏其倡导的类型安全的C++程序员来说,这是无法接受的。

C++提供了一种新的类型转换运算符,专门用于继承的情形,这种情形在C语言中并不存在。

4个C++类型运算符如下:

static_cast

dynamic_cast

reinterpret_cast

const_cast

1、static_cast

①用于相关类型的指针之间的转换

这个相关类型指针是指:具有继承关系的类的指针。

static_cast实现了基本的编译阶段检查,确保指针被转换为相关类型。使用static_cast可将指针向上转换为基类类型,也可向下转换为派生类类型。

这改进了C风格类型转换,在C语言中可将指向一个对象的指针转换为完全不相关的类型,而编译器不会报错。(C语言十分自由,而C++对于不同用途的类型转换,会有一些不同的约束)

注意:static_cast只验证指针类型是否相关(是否有继承关系类的指针),而不执行任何运行阶段检查。(故称之为静态static转换)

例:

CBase*pBase = new CBase( ) ;

CDerived*pDerived = static_cast<CDerived*>(pBase) ;

由于static_cast只在编译阶段检查转换类型是否相关,而不执行运行阶段检查,因此上面代码能够编译通过,但在运行阶段可能导致意外结果。

static_cast 与C风格的类型转换类似,只是static_cast只用于有继承相关性的类的指针。它会对这个关系进行检查。

故:

用static_cast把指向派生类的基类指针 转换为派生类指针,底层的派生类对象不变,指针的值也不变,只是改变了指针的管辖范围。即:只是改变了编译器的解释方式。(基类指针实际上指向的只是派生类中的基类核心)

同理,用static_cast把指向派生类的派生类指针 转换为基类指针,也只是改变了编译器对其的解释方式。(static_cast对与多重继承的指针,有特殊处理)

②用于内置数据类型的类型转换

例:

double dPi = 3.14;

int nNum =static_cast<int>(dPi) ;

使用static_cast可让代码阅读者注意到这里使用了类型转换,并指出编译器根据编译阶段可用信息进行了必要的调整,以便执行所需的类型转换。

2、dynamic_cast

dynamic_cast动态类型转换在运行阶段执行类型转换。可检查dynamic_cast操作的结果以判断类型转换是否成功。

dynamic_cast可以把基类指针转换为派生类指针,也可以把派生类指针转换为基类指针。如果转换后可以安全使用,则转换成功,否则其返回NULL。(而static_cast的转换,无法检查转换后的结果是否可以安全使用)

若基类指针指向的是基类对象,则把它dynamic_cast为派生类指针,则转换会失败。因为这是不安全的转换。

若基类指针指向的是派生类对象,则把它dynamic_cast为派生类指针,则转换会成功。这是安全的转换。(dynamic_cast比static_cast检查更加严格,但使用范围更小)

【注意】dynamic_cast必须要在有虚函数的继承里进行。(static_cast则无此限制)

给定一个基类指针,程序员可能不确定,它目前指向哪种类型,这时可使用dynamic_cast在运行时判断其类型,并在安全时使用转换后的指针。

dynamic_cast这种在运行阶段识别对象类型的机制成为 运行阶段类型识别RTTI。

关于RTTI

RTTI是Runtime Type Information的缩写,从字面上来理解就是执行期的类型信息,其重要作用就是动态判别执行期的类型。

即:判断基类指针或引用,目前所绑定的类型。

它有两种方法来识别:

①用dynamic_cast类型转换是否成功来识别类型。(dynamic_cast必须要在有虚函数的继承里进行)

例:

void fun(CBase* pBase)
{
CDerived* pDerived = dynamic_cast<CDerived*>(pBase) ;
if (pDerived != NULL)
pDerived->funDerived ;
else
pDerived->funBase ;
}

②用typeid判断基类地址是否一致来识别类型

例:

void fun(CBase* pBase)
{
CDerived* pDerived = NULL ;
if (typeid(*pBase) == typeid(CDerived))
{
pDerived = static_cast<CDerived*>(pBase) ;
pDerived->funDerived ;
}
else
pDerived->funBase ;
}

编译器从类中虚指针指向的虚函数表的前一表项中提取typeid的值。(请看 C++对象模型简介

【一般地讲,能用虚函数解决的问题就不要用“dynamic_cast”,能够用“dynamic_cast”解决的问题就不要用“typeid”。】

RTTI破坏了面向对象的纯洁性。

首先,它破坏了抽象。用RTTI检测当前基类指针绑定的类型,这与虚函数提倡的隐藏细节,智能实现多态相违背。

其次,因为运行时类型的不确定性,它把程序变得更脆弱。

第三,它使程序缺乏扩展性。当你在继承关系中加入了一个新类型时,你可能需要修改涉及RTTI的代码。

static_cast AND dynamic_cast的更多相关文章

  1. static_cast 和 dynamic_cast 的区别

    static_cast一般用来将枚举类型转换成整型,或者整型转换成浮点型.也可以用来将指向父类的指针转换成指向子类的指针.做这些转换前,你必须确定要转换的数据确实是目标类型的数据,因为static_c ...

  2. c++中的强制转换static_cast、dynamic_cast、reinterpret_cast的不同用法儿

    c++中的强制转换static_cast.dynamic_cast.reinterpret_cast的不同用法儿   虽然const_cast是用来去除变量的const限定,但是static_cast ...

  3. C++强制类型转换:static_cast、dynamic_cast、const_cast、reinterpret_cast

    1. c强制转换与c++强制转换 c语言强制类型转换主要用于基础的数据类型间的转换,语法为: (type-id)expression//转换格式1 type-id(expression)//转换格式2 ...

  4. C++中static_cast和dynamic_cast强制类型转换

    在C++标准中,提供了关于类型层次转换中的两个关键字static_cast和dynamic_cast. 一.static_cast关键字(编译时类型检查) 用法:static_cast < ty ...

  5. C++的类型转换:static_cast、dynamic_cast、reinterpret_cast和const_cast

    在C++中,存在类型转换,通常意味着存在缺陷(并非绝对).所以,对于类型转换,有如下几个原则:(1)尽量避免类型转换,包括隐式的类型转换(2)如果需要类型转换,尽量使用显式的类型转换,在编译期间转换( ...

  6. 四种强制类型转换的总结(const_cast、static_cast、dynamic_cast、reinterpreter_cast)

    四种强制类型转换的总结(const_cast.static_cast.dynamic_cast.reinterpreter_cast) 转载 2011年10月03日 23:59:05 标签: stru ...

  7. static_cast、dynamic_cast、reinterpret_cast、和const_cast

    关于强制类型转换的问题,很多书都讨论过,写的最详细的是C++ 之父的<C++ 的设计和演化>.最好的解决方法就是不要使用C风格的强制类型转换,而是使用标准C++的类型转换符:static_ ...

  8. static_cast 和 dynamic_cast

    1.static_cast static_cast < type-id > ( expression ) 该运算符把expression转换为type-id类型,但没有运行时类型检查来保证 ...

  9. C++ ------ static_cast,dynamic_cast,reinterpret_cast,const_cast

    C++类型转换分为:隐式类型转换和显式类型转换 第1部分. 隐式类型转换 又称为“标准转换”,包括以下几种情况:1) 算术转换(Arithmetic conversion) : 在混合类型的算术表达式 ...

  10. static_cast、dynamic_cast、const_cast和reinterpret_cast总结(转)

    前言 这篇文章总结的是C++中的类型转换,这些小的知识点,有的时候,自己不是很注意,但是在实际开发中确实经常使用的.俗话说的好,不懂自己写的代码的程序员,不是好的程序员:如果一个程序员对于自己写的代码 ...

随机推荐

  1. CUDA 纹理内存

    原文链接 1.概述 纹理存储器中的数据以一维.二维或者三维数组的形式存储在显存中,可以通过缓存加速访问,并且可以声明大小比常数存储器要大的多. 在kernel中访问纹理存储器的操作称为纹理拾取(tex ...

  2. 第50章 读写内部FLASH—零死角玩转STM32-F429系列

    第50章     读写内部FLASH 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/fire ...

  3. 第31章 TIM—基本定时器—零死角玩转STM32-F429系列

    第31章     TIM—基本定时器 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/fire ...

  4. EBS补丁时遇到的问题

    今天在给R12.1.3打17525552的时候,出现了这样的一个错误 ATTENTION: All workers either have failed or are waiting: FAILED: ...

  5. sql语句(Oracle和sqlserver)

    查询表的首句:(Oracle) select * from (select a.*, rownum as rn from tab_name a order by col )where rn = 1 o ...

  6. python的运行过程剖析·编程语言分类

    总结: 编程语言的分类 编译型: 说明:与汇编语言类似,都有一个编译程序将源代码编译成硬件可执行的二进制代码 特点:执行速度快.同等情况下对系统要求低,适合于开发大型应用程序.数据库系统.操作系统等 ...

  7. python学习之map函数和reduce函数的运用

    MapReduce:面向大型集群的简化数据处理引文 map()函数 Python中的map()函数接收两个参数,一个是调用函数对象(python中处处皆对象,函数未实例前也可以当对象一样调用),另一个 ...

  8. C语言字符篇(二)字符串处理函数

    字符串处理函数 1. 拷贝 strcpy 2. 追加 strcat   #include <string.h>   char *strcpy(char *dest, const char ...

  9. contest0 from codechef

    A  CodeChef - KSPHERES 中文题意  Mandarin Chinese Eugene has a sequence of upper hemispheres and another ...

  10. python基础之正则表达式爬虫应用,configparser模块和subprocess模块

    正则表达式爬虫应用(校花网) 1 import requests 2 import re 3 import json 4 #定义函数返回网页的字符串信息 5 def getPage_str(url): ...