关于强制类型转换的问题,很多书都讨论过,写的最详细的是C++ 之父的《C++ 的设计和演化》。最好的解决方法就是不要使用C风格的强制类型转换,而是使用标准C++的类型转换符:static_cast, dynamic_cast。标准C++中有四个类型转换符:static_cast、dynamic_cast、reinterpret_cast、和const_cast。下面对它们一一进行介绍。

static_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属性。

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:

int m_iNum;

virtual void foo();

};

class D:public B{

public:

char *m_szName[100];

};

void func(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则没有这个限制。这是由于运行时类型检查需要运行时类型信息,而这个信息存储在类的虚函数表(关于虚函数表的概念,详细可见<Inside c++ object model>)中,只有定义了虚函数的类才有虚函数表,没有定义虚函数的类是没有虚函数表的。

另外,dynamic_cast还支持交叉转换(cross cast)。如下代码所示。
class A{

public:

int m_iNum;

virtual void f(){}

};

class B:public A{

};

class D:public A{

};

void foo(){

B *pb = new B;

pb->m_iNum = 100;

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

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

delete pb;

}

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

reinpreter_cast

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

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

该运算符的用法比较多。

const_cast

用法:const_cast<type_id> (expression_r_r)

该运算符用来修改类型的const或volatile属性。除了const 或volatile修饰之外, type_id和expression_r_r的类型是一样的。

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

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

public:

int m_iNum;

}

void foo(){

const B b1;

b1.m_iNum = 100; //comile error

B b2 = const_cast<B>(b1);

b2. m_iNum = 200; //fine
}

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

最容易理解的解释:

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

static_cast、dynamic_cast reinterpret_cast的更多相关文章

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

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

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

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

  3. static_cast、dynamic_cast、reinterpret_cast、和const_cast

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

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

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

  5. static_cast、dynamic_cast、const_cast和reinterpret_cast总结

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

  6. C++里的强制类型转换符reinterpret_cast、static_cast 、dynamic_cast、const_cast 区别

    C 风格(C-style)强制转型如下: (T) exdivssion // cast exdivssion to be of type T 函数风格(Function-style)强制转型使用这样的 ...

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

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

  8. C++的static_cast、dynamic_cast和const_cast用法

    static_cast.dynamic_cast和const_cast static_cast: ​ 用法: static_cast < type-id > (expression) ​ ...

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

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

随机推荐

  1. Spark2.0 VS Spark 1.* -------SparkSession的区别

    Spark .0以前版本: val sparkConf = new SparkConf().setAppName("soyo") val spark = new SparkCont ...

  2. xfs文件备份恢复篇一vm中linux新增磁盘

    XFS提供了 xfsdump 和 xfsrestore 工具协助备份XFS文件系统中的数据.xfsdump 按inode顺序备份一个XFS文件系统.centos7选择xfs格式作为默认文件系统,而且不 ...

  3. $P5018 对称二叉树$

    problem 一直忘记给这个题写题解了. 这题挺水的吧. 挺后悔当时没写出来. #ifdef Dubug #endif #include <bits/stdc++.h> using na ...

  4. [转]c# 对密码执行散列和 salt 运算方法

    本文转自:http://www.cnblogs.com/CnBlogFounder/archive/2008/07/04/1235690.html 大家对密码执行散列和Salt运算一定不陌生.两个Vi ...

  5. Java常用类库(一) : Object 和日期类的简单使用

    顶哥说:Java是世界的,但项目不是! Java有非常多的类库,而我们不会也不用都去学习,毕竟你也仅仅掌握了你手机20%的功能却足够你使用,不是吗? 今天介绍以下类: l  Object l  Dat ...

  6. 百度之星2017初赛B1006 小小粉丝度度熊

    思路: 考虑到补签卡一定是连续放置才更优,所以直接根据起始位置枚举.预先处理区间之间的gap的前缀和,在枚举过程中二分即可.复杂度O(nlog(n)). 实现: #include <iostre ...

  7. Object未定义

    js加载时会在jquery中报Object未定义的错误? 原因: 页面和iframe页面中都引入了jquery 或者 是页面中包含iframe,并且在iframe没有完成加载前操作了iframe中的j ...

  8. dubbo之延迟连接及粘滞链接接

    延迟连接 延迟连接用于减少长连接数.当有调用发起时,再创建长连接.1 <dubbo:protocol name="dubbo" lazy="true" / ...

  9. 使用LocalDB部署Asp.Net MVC网站时遇到的问题

    首先一句话介绍LocalDB.LocalDB是SQLServer的文件数据库,类似于SQLite.它拥有SQLServer的绝大部分功能,简单易用.但部署LocalDB到生产系统是不推荐的.本文部署是 ...

  10. [问题记录]-技术学习-RocketMQ-全球集群部署问题

    一:问题场景 公司在部署全球的RocketMQ的时候,遇到亚洲区的服务器往欧洲区的RocketMQ发送消息失败的情况. 总共有出现两个问题 1:No Topic Route Info org.apac ...