• C++强制类型转换


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

    C强制转换

      C语言中的强制转换主要用于普通数据类型、指针的强制转换,没有类型检查,转换不安全,语法为:

    (type-id)expression//转换格式1
    type-id(expression)//转换格式2

      C++除了能使用c语言的强制类型转换外,还新增了四种强制类型转换:static_cast、dynamic_cast、const_cast、reinterpret_cast,主要运用于继承关系类间的强制转化,语法为:

    //静态转换
    static_cast<new_type>      (expression)
    //动态转换
    dynamic_cast<new_type>     (expression) 
    //常量转换
    const_cast<new_type>       (expression) 
    //重新解释转换
    reinterpret_cast<new_type> (expression)

      其中new type为转换后的新类型,expression为旧类型

    C++强制类型转换

    1. static_cast 静态转换(编译时检查)

      static_cast静态转换相当于C语言中的强制转换,但不能实现普通指针数据(空指针除外)的强制转换,一般用于父类和子类指针、引用间的相互转换。

      ①用于类层次结构中基类(父类)和派生类(子类)之间指针或引用的转换。不管是否发生多态,父子之间互转时,编译器都不会报错。

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

        进行下行转换(把基类指针或引用转换成派生类表示)时,由于没有动态类型检查,所以是不安全的,但是编译器不会报错。

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

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

      ④把任何指针类型转换成空指针类型。

      ⑤可以对普通数据的const和non_const进行转换,但不能对普通数据取地址后的指针进行const添加和消去。

      ⑥无继承关系的自定义类型,不可转换,不支持类间交叉转换。

      注意:static_cast不能转换掉expression的const、volatile、或者__unaligned属性
     1 class Person{
     2 
     3 };
     4 
     5 class Son :public Person{
     6 
     7 };
     8 
     9 class My{};
    10 
    11 void test02(){
    12     char a = 'c';
    13     int b = static_cast<int> (a);
    14     cout << b << endl;
    15 
    16     const char a0 = 'c';
    17     char b0 = static_cast<char> (a0);
    18     cout << b0 << endl;
    19 
    20     char a1 = 'c';
    21     const char b1 = static_cast<const char> (a1);
    22     cout << b1 << endl;
    23 
    24     //static无法丢掉常量或其他类型限定符,只限于对常量地址的指针去const
    25     //const char a2 = 'c';
    26     //char *b2 = static_cast<char*> (&a2);
    27     //cout << b2 << endl;
    28 
    29     
    30     //父类指针转为子类
    31     Person *p = NULL;
    32     Son *s = static_cast<Son*>(p);
    33 
    34     //子类指针转为父类
    35     Son *s0 = NULL;
    36     Person *p0 = static_cast<Person*>(s0);
    37 
    38     //My* my= static_cast<My*>(p); 无继承关系的自定义数据类型不能相互转换
    39 
    40     //父类对象无法转为子类对象
    41     //Person p1;
    42     //Son s1 = static_cast<Son>(p1);
    43     
    44     //子类对象可以赋值,初始化父类对象
    45     Son s2;
    46     Person p2 = static_cast<Person>(s2);
    47 
    48     //父类引用转为子类
    49     Person p_ ;
    50     Person &p3 = p_;
    51     Son &s3 = static_cast<Son&>(p3);
    52 
    53     //子类引用转为父类
    54     Son s_;
    55     Son &s4 = s_;
    56     Person &p4 = static_cast<Person&>(s4);
    57 
    58     //空指针转化为目标类型的指针
    59     void *pPtr = NULL;
    60     int *iPtr = static_cast<int*>(pPtr);
    61 
    62     //任何指针转化为空指针类型
    63     int *aInt = NULL;
    64     void *aVoid = static_cast<void*>(aInt);
    65 
    66     //static_cast不能进行出void外的指针强制互转
    67     char *tmp = "abc";
    68     cout << tmp << endl;
    69 
    70     //cout << static_cast<int*>(tmp) << endl;不能将char*型的数据转换为int*,但C语言强转可以
    71     cout << static_cast<void*>(tmp) << endl;
    72 
    73     int *tmp_ = (int*)(tmp); 
    74     cout << static_cast<int*>(tmp_) << endl;
    75 
    76     int *tmpInt = 0;
    77     cout << tmpInt << endl;
    78     cout << static_cast<void*>(tmpInt) << endl;
    79     cout << static_cast<int*>(tmpInt) << endl;//转为自身可以
    80 }

    2.dynamic_cast 动态转换(运行时检查)

      动态转换的类型和操作数必须是完整类类型或空指针、空引用,说人话就是说,只能用于类间转换,支持类间交叉转换,不能操作普通数据

      主要用于类层次结构中基类(父类)和派生类(子类)之间指针或引用的转换,

        ①进行上行转换(把派生类的指针或引用转换成基类表示)是安全的,允许转换;

        ②进行下行转换(把基类指针或引用转换成派生类表示)时,由于没有动态类型检查,所以是不安全的,不允许转化,编译器会报错;

        ③发生多态时,允许互相转换。

        ④无继承关系的类之间也可以相互转换,类之间的交叉转换。

        ⑤如果dynamic_cast语句的转换目标是指针类型并且失败了,则结果为0。如果转换目标是引用类型并且失败了,则dynamic_cast运算符将抛出一个std::bad_cast异常

    3. const_cast 常量转换

      const_cast,用于修改类型的const或volatile属性,不能对非指针或非引用的变量添加或移除const。

     1 const int g = 20;
     2 //int h = const_cast<int>(g); //不允许对普通数据进行操作
     3 int *h = const_cast<int*>(&g);//去掉const常量const属性
     4 
     5 const int g0 = 20;
     6 const int &g2 = g0;
     7 int &h = const_cast<int &>(g0);//去掉const引用const属性
     8 int &h2 = const_cast<int &>(g2);//去掉const引用const属性
     9 
    10 const char *g1 = "hello";
    11 char *h = const_cast<char *>(g1);//去掉const指针const属性

    4.reinterpret_cast 重新解释转换

      最鸡肋的转换函数,可以将任意类型转换为任意类型,因此非常不安全。只有将转换后的类型值转换回到其原始类型,这样才是正确使用reinterpret_cast方式。

      另外,static_cast和reinterpret_cast的区别主要在于多重继承,比如

     1 class A {
     2     public:
     3     int m_a;
     4 };
     5  
     6 class B {
     7     public:
     8     int m_b;
     9 };
    10  
    11 class C : public A, public B {};
    12 
    13 void test(){
    14     C c;
    15     printf("%p, %p, %p", &c, reinterpret_cast<B*>(&c), static_cast <B*>(&c));
    16 }

      前两个的输出值是相同的,最后一个则会在原基础上偏移4个字节,这是因为static_cast计算了父子类指针转换的偏移量,并将之转换到正确的地址(c里面有m_a,m_b,转换为B*指针后指到m_b处),而reinterpret_cast却不会做这一层转换

  • 相关阅读:
    Bzoj 3173: [Tjoi2013]最长上升子序列 平衡树,Treap,二分,树的序遍历
    Bzoj 1657: [Usaco2006 Mar]Mooo 奶牛的歌声 单调栈
    Bzoj 1391: [Ceoi2008]order 网络流,最大权闭合图
    Bzoj 1674: [Usaco2005]Part Acquisition dijkstra,堆
    Bzoj 3110: [Zjoi2013]K大数查询 树套树
    Cogs 309. [USACO 3.2] 香甜的黄油 dijkstra,堆,最短路,floyd
    面试题24:二叉排序树的后序遍历序列
    面试题23:从上往下打印二叉树
    面试题22:栈的压入、弹出序列
    面试题21:包含min函数的栈
  • 原文地址:https://www.cnblogs.com/qinguoyi/p/10303912.html
Copyright © 2020-2023  润新知