关于强制类型转换的问题,许多书都讨论过,写的最具体的是C++之父的《C++的设计和演化》。

最好的解决方法就是不要使用C风格的强制类型转换,而是使用标准C++的类型转换符:static_cast,dynamic_cast。

标准C++中有四个类型转换符:static_cast、dynamic_cast、reinterpret_cast、和const_cast。

以下对它们一一进行介绍。

1、const_cast通常被用来将对象的常量刑转换。它也是唯一有此能力的C++-style转型操作符。

使用方法:const_cast<type_id>(expression_r_r)

该运算符用来改动类型的const或volatile属性。

除了const或volatile修饰之外, type_id和expression_r_r的类型是一样的。

常量指针被转化成很量指针。而且仍然指向原来的对象;常量引用被转换成很量引用,而且仍然指向原来的对象。常量对象被转换成很量对象。

Voiatile和const类试。举例如以下一例:
class B{

public:

intm_iNum;

}

voidfoo(){

const Bb1;

b1.m_iNum = 100;//comile error

B b2= const_cast<B>(b1);

b2.m_iNum = 200; //fine
}

上面的代码编译时会报错。因为b1是一个常量对象,不能对它进行改变;使用const_cast把它转换成一个常量对象。就能够对它的数据成员随意改变。注意:b1和b2是两个不同的对象。

2、dynamic_cast主要用来运行“安全向下转型”。也就是用来决定某对象是否归属继承体系中的某个实现。他是唯一无法由旧式语法运行的动作。也是唯一可能耗费重大运行成本的转型动作。

使用方法:dynamic_cast< type-id > ( expression_r_r)

该运算符把expression_r_r转换成type-id类型的对象。

Type-id必须是类的指针、类的引用或者void*;假设type-id是类指针类型。那么expression_r_r也必须是一个指针,假设type-id是一个引用。那么expression_r_r也必须是一个引用。

dynamic_cast主要用于类层次间的上行转换和下行转换。还能够用于类之间的交叉转换。

在类层次间进行上行转换时,dynamic_cast和static_cast的效果是一样的。在进行下行转换时,dynamic_cast具有类型检查的功能,比static_cast更安全。
class B{

public:

intm_iNum;

virtual voidfoo();

};

class D:publicB{

public:

char*m_szName[100];

};

 

voidfunc(B *pb){

D*pd1 = static_cast<D*>(pb);

D*pd2 = dynamic_cast<D*>(pb);

}

在上面的代码段中。假设pb指向一个D类型的对象。pd1和pd2是一样的。而且对这两个指针运行D类型的不论什么操作都是安全的。可是,假设pb指向的是一个B类型的对象。那么pd1将是一个指向该对象的指针,对它进行D类型的操作将是不安全的(如訪问m_szName),而pd2将是一个空指针。另外要注意:B要有虚函数,否则会编译出错。static_cast则没有这个限制。这是因为运行时类型检查须要运行时类型信息,而这个信息存储在类的虚函数表(关于虚函数表的概念,具体可见<Insidec++
objectmodel>)中,仅仅有定义了虚函数的类才有虚函数表,未定义虚函数的类是没有虚函数表的。

另外。dynamic_cast还支持交叉转换(crosscast)。

例如以下代码所看到的。
class A{

public:

intm_iNum;

virtual voidf(){}

};

 

class B:publicA{

};

 

class D:publicA{

};

 

voidfoo(){

B*pb = new B;

pb->m_iNum= 100;

D*pd1 = static_cast<D *>(pb); //copileerror

D*pd2 = dynamic_cast<D *>(pb); //pd2is NULL

deletepb;

}

在函数foo中,使用static_cast进行转换是不被同意的。将在编译时出错。而使用dynamic_cast的转换则是同意的,结果是空指针。

3、reinterpret_cast意图运行低级转型,实际动作(及结果)可能取决于编译器。这也就表示它不可移植。比如将一个pointer to int转型为一个int,这一类转换在低级代码意外很少见到。

使用方法:reinpreter_cast<type-id>(expression_r_r)

type-id必须是一个指针、引用、算术类型、函数指针或者成员指针。它能够把一个指针转换成一个整数,也能够把一个整数转换成一个指针(先把一个指针转换成一个整数。在把该整数转换成原类型的指针。还能够得到原先的指针值)。

该运算符的使用方法比較多。

4、static_cast用来强迫隐式转换,比如将non-const对象转换为const相应,或将int转换为double等等。它也能够用来运行上述多种转换的反向转换,比如将void*指针转为typed指针。将pointer-to-base转为pointer-to-derived。但无法将const转为non-const(这个仅仅用const_cast才干办到)

使用方法:static_cast< type-id > ( expression_r_r)

该运算符把expression_r_r转换为type-id类型,但没有运行时类型检查来保证转换的安全性。它主要有例如以下几种使用方法

用于类层次结构中基类和子类之间指针或引用的转换。

进行上行转换(把子类的指针或引用转换成基类表示)是安全的;进行下行转换(把基类指针或引用转换成子类表示)时,因为没有动态类型检查,所以是不安全的。

用于基本数据类型之间的转换。如把int转换成char。把int转换成enum。

这样的转换的安全性也要开发者来保证。

把空指针转换成目标类型的空指针。
把不论什么类型的表达式转换成void类型。
注意:static_cast不能转换掉expression_r_r的const、volitale、或者__unaligned属性。

假设打算将常量性去掉。除非使用新式转型中的const_cast 否则无法通过编译。

最easy理解的解释:

  dynamic_cast:   通常在基类和派生类之间转换时使用。
   const_cast:  主要针对const和volatile的转换.   
   static_cast: 一般的转换,假设你不知道该用哪个,就用这个。   
   reinterpret_cast:  用于进行没有不论什么关联之间的转换,比方一个字符指针转换为一个整形数。

C++提供的四种新式转换--const_cast dynamic_cast reinterpret_cast static_cast的更多相关文章

  1. C++中四种类型转换以及const_cast是否能改变常量的问题

    we have four specific casting operators:dynamic_cast, reinterpret_cast, static_cast and const_cast. ...

  2. [C++][操作符]四种显示转换操作符

    整理了C++ Primer中提到的四种显示转换,用思维导图写出来,是不是很清晰O(∩_∩)O.

  3. javaSE中JDK提供的四种线程池

    对javaSE中JDK提供的四种线程池稍作整理   一.Executor   package java.util.concurrent; /** * @since 1.5 * @author Doug ...

  4. OAuth2 RFC 6749 规范提供的四种基本认证方案

    OAuth2 RFC 6749 规范提供了四种基本认证方案,以下针对这四种认证方案以及它们在本实现中的使用方式进行分别说面. 第一种认证方式: Authorization Code Grant (授权 ...

  5. JAVA基础知识|Executors提供的四种线程池

    一.Thread与Executors 开启新的线程,我们经常会采用如下方法: Thread thread =new Thread(new Runnable() { @Override public v ...

  6. C++ 四种显示转换

    转自:http://www.jellythink.com/archives/205   (果冻想) 前言 这篇文章总结的是C++中的类型转换,这些小的知识点,有的时候,自己不是很注意,但是在实际开发中 ...

  7. C++四种强制转换

    C++的四种强制类型转换,所以C++不是类型安全的.分别为:static_cast , dynamic_cast , const_cast , reinterpret_cast 为什么使用C风格的强制 ...

  8. 面试问题之C++语言:说一说C++中四种cast转换

    C++中四种类型转换是:static_cast.dynamic_cast.const_cast.reinterpret_cast 1.const_cast 常量转换,用于将const变量转为非cons ...

  9. JDK提供的四种线程池代码详解

    一.线程池什么时候使用,会给我们带来什么好处? 如果很多用户去访问服务器,用户访问服务器的时间是非常短暂的,那么有可能在创建线程和销毁线程上花费的时间会远远大于访问所消耗的时间,如果采用线程池会使线程 ...

随机推荐

  1. php获取当前被调函数的参数列表

    下面是php中的一个获取当前别调用函数的参数列表的测试程序,感受一下php类库的强大之处: // 测试获取参数列表 getArgs('aaa', 'bbb', 'ccc', 123, true); f ...

  2. 高性能前端 art-template 模板

    官网: https://aui.github.io/art-template/zh-cn/index.html nodejs 服务器端使用 第一步: 引入 art-template 的包 npm in ...

  3. Syncfusion SfDataGrid 导出Excel

    var options = new ExcelExportingOptions { ExcelVersion = ExcelVersion.Excel2013, }; //不需要导出的字段 optio ...

  4. Halcon 彩色图片通道分割处理

    1.RGB通道:R红色,G绿色,B蓝色:R.G.B各占一个字节,取值范围在0—255:可代表的颜色数256*256*256==2^24 黑色区域是:R=G=B=0;   白色区域是:R=G=B=255 ...

  5. Linux解压缩命令tar

    tar -c: 建立压缩档案-x:解压-t:查看内容-r:向压缩归档文件末尾追加文件-u:更新原压缩包中的文件 这五个是独立的命令,压缩解压都要用到其中一个,可以和别的命令连用但只能用其中一个.下面的 ...

  6. 使用Go语言操作MySQL数据库的思路与步骤

    最近在做注册登录服务时,学习用Go语言操作MySQL数据库实现用户数据的增删改查,现将个人学习心得总结如下,另外附有代码仓库地址,欢迎各位有兴趣的fork. 软件环境:Goland.Navicat f ...

  7. vs 2015 项目筛选器没了,.h头文件和.cpp文件混在一起了

    场景: git 拉取 VS 2015 项目,打开之后,.h头文件和.cpp文件混在一起了. 解决方案: 需要XXX..vcxproj.filters 文件.

  8. [sqoop] sqoop2 使用

    sqoop版本1.99.7 ,安装省略 1. 启动server sqoop2-server start 2. sqoop2-shell 链接 表示安装成功. 创建link 查看link 创建job 查 ...

  9. Android remount命令的两种写法

    不同系统的参数格式可能不一样,而且可能没有--help打印,记录一下: mount -o remount -rw /system mount -o remount,rw /system

  10. 【奇淫技巧】API接口字段table文档转代码工具

    今天做一个视频接口对接,发现对方提供的文档没有json格式,无法自动生成请求和响应对象 json自动生成C#类的工具 http://tool.sufeinet.com/Creater/JsonClas ...