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

static_cast

用法:static_cast < type-id > ( expression )

  该运算符把expression转换为type-id类型,但没有运行时类型检查来保证转换的安全性。它主要有如下几种用法: 
用于类层次结构中基类和子类之间指针或引用的转换。进行上行转换(把子类的指针或引用转换成基类表示)是安全的;进行下行转换(把基类指针或引用转换成子类表示)时,由于没有动态类型检查,所以是不安全的。 
  用于基本数据类型之间的转换,如把int转换成char,把int转换成enum。(这种转换的安全性也要开发人员来保证。) 
  把空指针转换成目标类型的空指针。 
  把任何类型的表达式转换成void类型。

  注意:static_cast不能转换掉expression的const、volitale、或者__unaligned属性。

dynamic_cast

用法:dynamic_cast < type-id > ( expression )

  该 运算符把expression转换成type-id类型的对象。Type-id必须是类的指针、类的引用或者void *;如果type-id是类指针类型,那么expression也必须是一个指针,如果type-id是一个引用,那么expression也必须是一个引用。

  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[];
}; 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 = ; 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)

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

该运算符的用法比较多。

const_cast

用法:const_cast<type_id> (expression)

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

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

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

class B
{
public:
int m_iNum; } void foo()
{ const B b1;
b1.m_iNum = ; //comile error B b2 = const_cast<B>(b1);
b2. m_iNum = ; //fine
}

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

static_cast、dynamic_cast、reinterpret_cast、和const_cast的更多相关文章

  1. c++ 数据类型转换: static_cast dynamic_cast reinterpret_cast const_cast

    c++ 数据类型转换: static_cast dynamic_cast reinterpret_cast const_cast  [版权声明]转载请注明出处 http://www.cnblogs.c ...

  2. C++雾中风景11:厘清C++类型转换(static_cast,dynamic_cast,reinterpret_cast,const_cast)

    C++是一门弱类型的语言,提供了许多复杂和灵巧类型转换的方式.笔者之前写的Python与Go都是强类型的语言,对这种弱类型的设计实在是接受无力啊~~ ( 生活所迫,工作还得写C++啊~~)C++语言提 ...

  3. C++ static_cast dynamic_cast reinterpret_cast const_cast转换

    static_cast <type-id> ( expression ) 和C风格的类型转换相似,可以转换一个指针到基类,或者派生类.不做Run-time类型检查,这样转换并不总是安全的. ...

  4. static_cast, dynamic_cast, reinterpret_cast, const_cast区别比较

    隐式转换(implicit conversion) ; int b; b=a; short是两字节,int是四字节,由short型转成int型是宽化转换(bit位数增多),编译器没有warning,如 ...

  5. static_cast, dynamic_cast, reinterpret_cast, const_cast的区别

    static_cast最像C风格的强制转换,很多时候都需要程序员自身去判断转换是否安全.但是相对C风格的强制转换,在无关类的类指针之间转换上,有安全性的提升. dynamic_cast是运行时的转换吧 ...

  6. 你也许还不知道const_cast,static_cast,dynamic_cast,reinterpret_cast的区别吧?

    [QQ群: 189191838,对算法和C++感兴趣可以进来]       开篇立意: C++中各种转换令人眼花缭乱,看似差不多,实际差很多,而且在当今时间,做一个"差不多先生"其 ...

  7. static_cast、dynamic_cast、reinterpret_cast、const_cast以及C强制类型转换的区别

    static_cast 1. 基础类型之间互转.如:float转成int.int转成unsigned int等 2. 指针与void*之间互转.如:float*转成void*.CBase*转成void ...

  8. c++强制类型转换:dynamic_cast、const_cast 、static_cast、reinterpret_cast

    c++强制类型转换:dynamic_cast.const_cast .static_cast.reinterpret_cast 博客分类: C/C++ CC++C#编程数据结构  dynamic_ca ...

  9. dynamic_cast,const_cast,static_cast,reinterpret_cast 详解

    如果直接指针直接强转,将只能访问虚函数的内容,而不能访问特定类中的特定成员或方法!!!! 强制类型转换运算符:C++有四种强制类型转换符,分别是dynamic_cast,const_cast,stat ...

  10. C++提供的四种新式转换--const_cast dynamic_cast reinterpret_cast static_cast

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

随机推荐

  1. eclipse导入web项目各种错误

    1.JavaWeb:报错信息The superclass "javax.servlet.http.HttpServlet" was not found on the Java Bu ...

  2. 解决 maven 项目启动 提示 class not find

    第一种方法: 项目 --> .classpath <classpathentry exported="true" kind="con" path=& ...

  3. ubuntu移植jsoncpp到Android平台(转)

    NDK开发模块的时候,如果涉及到网络请求,类似json数据传递的时候,有现成的第三方json库可以移植,后台C++开发中使用的比较多的是jsoncpp,今天记录一下jsoncpp移植到Android平 ...

  4. libevent个人理解

    1.利用了前置声明来在c语言的基础上进行封装操作.即在include目录下防止event.h等头文件,在这些头文件中只暴露struct的声明却不暴露其定义,对于如event_base等结构的操作均使用 ...

  5. [C#]记录程序耗时的方法【转发】

    System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch(); stopwatch.Start(); // H ...

  6. HDU 1023 Train Problem II 大数打表Catalan数

    一个出栈有多少种顺序的问题.一般都知道是Catalan数了. 问题是这个Catalan数非常大,故此须要使用高精度计算. 并且打表会速度快非常多.打表公式要熟记: Catalan数公式 Cn=C(2n ...

  7. Python之zip

    # -*- coding: utf-8 -*- #python 27 #xiaodeng #Python之zip #http://python.jobbole.com/82590/ #1)zip语法格 ...

  8. 500 OOPS: chroot

    FTP登录时报错: 1.500 OOPS: chroot 解决方法:关闭SElinux 2.500 OOPS: vsftpd: refusing to run with writable root i ...

  9. Intellij IDEA 设置代码着色

    从visual studio到Eclipse再到Intllij IDEA,其实每个编译器都有自己的风格,但是就美观上来说,个人觉得还是visual studio的代码着色比较美观,exlipse次之, ...

  10. 百度UEditor富文本编辑器去除过滤div等标签

    将设计排版好的页面html代码上传到数据库,再读取出来的时候发现所有的div都被替换成了p标签. 解决方法: 首先在ueditor.all.js文件内搜索allowDivTransToP,找到如下的代 ...