zoukankan      html  css  js  c++  java
  • c++ 数据类型转换: static_cast dynamic_cast reinterpret_cast const_cast

    【目录】

    引言

    static_cast 定义

    dynamic_cast 定义

    举例:下行转换(把基类的指针或引用转换成子类表示)

    举例:上行转换(把子类的指针或引用转换成基类表示)

    举例: static_cast 用于基本类型之间、基本类型指针和空指针间的转换

    reinterpret_cast 定义

    举例:reinterpret_cast用法

    const_cast 定义

    举例:const_cast用法

    总结


    c语言中我们经常使用类似于 int a =(int)3.14等这种强制类型转换

    标准c++的类型转换符:static_cast 、dynamic_cast、 reindivter_cast、 const_cast, 以下分别介绍他们的用法以及举例说明

    以下代码编译运行环境:codeblock with gcc in win7(x64)

    【1】static_cast 
    用法:static_cast < type-id > ( exdivssion ) 

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

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

      进行上行转换(把子类的指针或引用转换成基类表示)是安全的;

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

    ②用于基本数据类型之间的转换,如把int转换成char,把int转换成enum。这种转换的安全性也要开发人员来保证。

    ③把空指针转换成目标类型的空指针。

    ④把任何类型的表达式转换成void类型。

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

    msdn官方解释:http://msdn.microsoft.com/en-us/library/c36yw7x9(v=vs.80).aspx

    【2】dynamic_cast

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

    该运算符把exdivssion转换成type-id类型的对象。Type-id必须是类的指针、类的引用或者void *;

    如果type-id是类指针类型,那么exdivssion也必须是一个指针,如果type-id是一个引用,那么exdivssion也必须是一个引用。

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

    在类层次间进行上行转换时,dynamic_cast和static_cast 的效果是一样的;

    在进行下行转换时,dynamic_cast具有类型检查的功能,比static_cast 更安全。

    msdn官方解释:http://msdn.microsoft.com/en-us/library/cby9kycs(v=vs.80).aspx

    举例:下行转换(把基类的指针或引用转换成子类表示)

    需要注意的是如果基类中不含虚函数,dynamic_cast 下行转换编译会出错

     1 #include<iostream>
     2 using namespace std;
     3 
     4 class father
     5 {
     6 public:
     7     void fun1()
     8     {
     9         cout<<"this is father fun1 call
    ";
    10     }
    11     virtual void fun()
    12     {
    13         cout<<"this is father fun call
    ";
    14     }
    15 };
    16 
    17 class son: public father
    18 {
    19 public:
    20     void fun2()
    21     {
    22         cout<<"this is son fun2 call
    ";
    23     }
    24     void fun()
    25     {
    26         cout<<"this is the son fun call
    ";
    27     }
    28     int k;
    29 };
    30 
    31 int main()
    32 {
    33     father *pf, f;
    34     son *ps, s;
    35 
    36     pf = &f;// 基类的指针指向基类对象
    37     ps = static_cast<son *>(pf);//这种转换是不安全的,行为是不确定的
    38     if(ps != NULL)
    39     {
    40         ps->fun(); //在本文编译环境下,执行父类的fun
    41         //本文编译环境下,一下语句可以执行
    42         ps->fun2();
    43         ps->k = 1;
    44     }
    45     ps = dynamic_cast<son *>(pf);//转换后ps = NULL
    46     if(ps == NULL)
    47         cout<<"dynamic_cast: ps = NULL
    ";
    48     cout<<"-----------------------------------------------------------------
    ";
    49     pf = &s; //基类指针开始指向子类对象
    50     //此时,两种转换都是安全的
    51     ps = static_cast<son *>(pf);
    52     if(ps != NULL)
    53     {
    54         ps->fun();
    55         ps->fun2();
    56         ps->k = 1;
    57     }
    58     ps = dynamic_cast<son *>(pf);//转换后ps = NULL
    59     if(ps != NULL)
    60     {
    61         ps->fun();
    62         ps->fun2();
    63         ps->k = 2;
    64     }
    65 }

    结果:

    举例:上行转换(把子类的指针或引用转换成基类表示)

     1 //类定义同上
     2 int main()
     3 {
     4     father *pf, f;
     5     son *ps, s;
     6 
     7     ps = &s;// 子类的指针指向子类对象
     8     //此时两种转换都是安全的
     9     pf = static_cast<father *>(ps);
    10     if(pf != NULL)
    11     {
    12         pf->fun();
    13     }
    14     pf = dynamic_cast<father *>(ps);
    15     if(pf != NULL)
    16     {
    17         pf->fun();
    18     }
    19 
    20 }

    举例: static_cast 用于基本类型之间、基本类型指针和空指针间的转换(不能用于基本类型指针之间转换)。

    注意:基本类型由于表示数值范围的不同,因此需要用户保证转换的安全。另外dynamic_cast不能用于此类转换

     1 int main()
     2 {
     3     //基本类型间的转换,需要用户保证安全
     4     int a = 1000;
     5     char c = static_cast<char>(a);//不安全,1000超过了char的表示范围
     6     cout<<c<<endl;//输出空
     7     a = 49;
     8     c = static_cast<char>(a);//安全,输出字符‘1’
     9     cout<<c<<endl;
    10     //c = dynamic_cast<char>(a); 错误
    11     cout<<"-----------------------------------------------------------------
    ";
    12     //void *和基本类型指针的转换,需要用户保证转换安全
    13     a = 49;
    14     void *pv;
    15     pv = &a;
    16     int *pi = static_cast<int *>(pv);//void * 转换为int *
    17     cout<<*pi<<endl; //输出49
    18     //pi = dynamic_cast<int *>(pv); 错误
    19     char *pc = static_cast<char *>(pv);//void *转char*
    20     cout<<*pc<<endl;//输出字符‘1’
    21     void *pv2 = static_cast<void *>(pc);// char * 转void *
    22     cout<<*((char *)pv2)<<endl;////输出字符‘1’
    23 }

    【3】reinterpret_cast

    用法:reinterpret_cast<type-id> (exdivssion)

    reinterpret_cast运算符是用来处理无关类型之间的转换;它会产生一个新的值,这个值会有与原始参数(expressoin)有完全相同的比特位。按照reinterpret的字面意思“重新解释”,即对数据的比特位重新解释。

    IBM的C++指南 里明确告诉了我们reinterpret_cast可以,或者说应该在什么地方用来作为转换运算符:

    • 从指针类型到一个足够大的整数类型
    • 从整数类型或者枚举类型到指针类型
    • 从一个指向函数的指针到另一个不同类型的指向函数的指针
    • 从一个指向对象的指针到另一个不同类型的指向对象的指针
    • 从一个指向类函数成员的指针到另一个指向不同类型的函数成员的指针
    • 从一个指向类数据成员的指针到另一个指向不同类型的数据成员的指针

    总结来说:reinterpret_cast用在任意指针(或引用)类型之间的转换;以及指针与足够大的整数类型之间的转换;从整数类型(包括枚举类型)到指针类型,无视大小。

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

    msdn官方解释:http://msdn.microsoft.com/en-us/library/e0w9f63b(v=vs.80).aspx

    举例:reinterpret_cast用法

     1 int main()
     2 {
     3    int a = 49;
     4    int *pi = &a;
     5    char *pc = reinterpret_cast<char*>(pi);//int * 到char *,用户自己安全
     6    cout<<*pc<<endl; //输出字符"1"
     7    unsigned long b = reinterpret_cast<unsigned long>(pc);//char * 转 unsigned long
     8    cout<<b<<endl;//输出pc指向地址(即a的地址)对应的整数
     9    int *pi2 = reinterpret_cast<int *>(b);//unsigned long 转 int*
    10    cout<<*pi2<<endl; //输出49
    11 }

    【4】const_cast 

    用法:const_cast<type-id> (exdivssion)

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

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

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

    msdn官方解释:http://msdn.microsoft.com/en-us/library/bz6at95h(v=vs.80).aspx

    举例:const_cast用法

    1 int main()
    2 {
    3    const int a = 100;
    4    int *b = const_cast<int *>(&a);//const int * 转int *
    5    cout<<*b<<endl; //输出100
    6    cout<<&a<<" "<<b<<endl; //两者值相同,表明b指向a的地址,只是const属性变了
    7 }


    总结:

    类指针或引用的上行转换static_cast 和 dynamic_cast 都可以

    类指针或引用的下行转换用dynamic_cast并且判断转换后是否为空

    基本数据类型之间的转换用static_cast, 但是由于数值范围的不同,需要用户保证转换的安全性

    不同类型之间的指针或引用的转换用reinterpret_cast,它的本质是对指向内存的比特位的重解释

    消除数据的const、volatile、__unaligned属性,用const_cast

    【版权声明】转载请注明出处 http://www.cnblogs.com/TenosDoIt/p/3175217.html

  • 相关阅读:
    SSM(六)JDK动态代理和Cglib动态代理
    SSM(三)Mybatis动态SQL
    MyBatis无限级分类实现的两种方法--自关联与map集合
    idea上MyBatis第一个例子
    idea 给maven项目添加依赖(二)
    idea 创建maven项目(一)
    Java学习笔记——三层架构
    MySQL实现自动使用uuid作为主键以及解决不能调用触发器的一点思路
    Java学习笔记——MySQL创建表结构
    jQuery入门——注册事件
  • 原文地址:https://www.cnblogs.com/TenosDoIt/p/3175217.html
Copyright © 2011-2022 走看看