ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

C++ 强制转换运算符 xxxx_cast

2022-08-08 10:04:51  阅读:271  来源: 互联网

标签:类型转换 xxxx reinterpret int C++ 运算符 cast 转换 指针


背景

类型转换的需求,C中有显示/隐式的强制类型转换。C++为了兼容保留了,但也提供了四种运算符来实现转换。

 

C语言强制类型转换的缺点

  • 从形式上无法判断功能和风险

  • 将多态基类指针转换成派生类指针时,没有检查安全性。无法判断转换后的指针是否指向一个派生类对象

  • 难以寻找使用转换的地方

 

C++提供的强制转换运算符:

格式:xxxx_cast<目标类型>(表达式)

 


static_cast

用处:

  • 整型、浮点型、字符型之间转换;

  • 如果对象重载了强制类型转换运算符T,也可以使用。

  • 子类可以转成父类,父类不能转成子类

特点:

  • 低风险

  • 编译时会进行类型转换的检查,需要保证转换的安全性和正确性

    (比如int* 不能转为int)

 

不能:(下面都是风险高的转换)

  • 不同类型的指针之间

  • 整型 指针之间

  • 不同类型的引用之间

 

例子:

#include <iostream>
using namespace std;
class A
{
public:
    operator int() { return 1; }
    operator char*() { return NULL; }
};
int main()
{
    A a;
    int n;
    char* p = "New Dragon Inn";
    n = static_cast <int> (3.14);  // n 的值变为 3
    n = static_cast <int> (a);  //调用 a.operator int,n 的值变为 1
    p = static_cast <char*> (a);  //调用 a.operator char*,p 的值变为 NULL
    n = static_cast <int> (p);  //编译错误,static_cast不能将指针转换成整型
    p = static_cast <char*> (n);  //编译错误,static_cast 不能将整型转换成指针
    return 0;
}

 


reinterpret_cast

用处:不同类型指针/引用之间、指针和整数类型之间。(但不会检查安全性)

 

特点:

  • 转换时,是逐个比特复制的操作

  • 强灵活性,安全性较差,由用户自己保证

  • 编译时进行类型转换检查

  • 可以将多态基类(包含虚函数的基类)的指针强制转换为派生类的指针。但不会检查安全性

 

例子:

#include <iostream>
using namespace std;
class A
{
public:
    int i;
    int j;
    A(int n):i(n),j(n) { }
};
int main()
{
    A a(100);
    int &r = reinterpret_cast<int&>(a); //强行让 r 引用 a
    r = 200;  //把 a.i 变成了 200
    cout << a.i << "," << a.j << endl;  // 输出 200,100
    int n = 300;
    A *pa = reinterpret_cast<A*> ( & n); //强行让 pa 指向 n
    pa->i = 400;  // n 变成 400
    pa->j = 500;  //此条语句不安全,很可能导致程序崩溃
    cout << n << endl;  // 输出 400
    long long la = 0x12345678abcdLL;
    pa = reinterpret_cast<A*>(la); //la太长,只取低32位0x5678abcd拷贝给pa
    unsigned int u = reinterpret_cast<unsigned int>(pa);//pa逐个比特拷贝到u
    cout << hex << u << endl;  //输出 5678abcd
    typedef void (* PF1) (int);
    typedef int (* PF2) (int,char *);
    PF1 pf1;  PF2 pf2;
    pf2 = reinterpret_cast<PF2>(pf1); //两个不同类型的函数指针之间可以互相转换
}
程序的输出结果是:
200, 100
400
5678abed

reinterpret_cast体现了 C++ 语言的设计思想:用户可以做任何操作,但要为自己的行为负责。

 


const_cast

用法:用于去除 const 属性

特点:

  • 编译时进行类型转换的检查

 

例子:

const string s = "Inception";
string& p = const_cast <string&> (s);
string* ps = const_cast <string*> (&s);  // &s 的类型是 const string*

 


dynamic_cast

用法:

是 reinterpret_cast 的补充,dynamic_cast专门用于将【多态基类的指针或引用】 强制转换为 【派生类的指针或引用】,而且能够检查转换的安全性。对于不安全的指针转换,转换结果返回 NULL 指针。

 

特点:

  • 运行时类型检查来保证安全性

 

不能:

  • 不能用于将【非多态基类】(即基类必须有 virtual )的指针或引用强制转换为派生类的指针或引用——这种转换没法保证安全性

 

例子:

#include <iostream>
#include <string>
using namespace std;
class Base
{  //有虚函数,因此是多态基类
public:
    virtual ~Base() {}
};
class Derived : public Base { };
int main()
{
    Base b;
    Derived d;
    Derived* pd;
    pd = reinterpret_cast <Derived*> (&b);
    if (pd == NULL)
        //此处pd不会为 NULL。reinterpret_cast不检查安全性,总是进行转换
        cout << "unsafe reinterpret_cast" << endl; //不会执行
    pd = dynamic_cast <Derived*> (&b);
    if (pd == NULL)  //结果会是NULL,因为 &b 不指向派生类对象,此转换不安全
        cout << "unsafe dynamic_cast1" << endl;  //会执行
    pd = dynamic_cast <Derived*> (&d);  //安全的转换
    if (pd == NULL)  //此处 pd 不会为 NULL
        cout << "unsafe dynamic_cast2" << endl;  //不会执行
    return 0;
}
程序的输出结果是:
unsafe dynamic_cast1

 

如果上面的程序中出现了下面的语句:

Derived & r = dynamic_cast <Derived &> (b);

那该如何判断该转换是否安全呢?不存在空引用,因此不能通过返回值来判断转换是否安全。

C++ 的解决办法是:dynamic_cast 在进行引用的强制转换时,如果发现转换不安全,就会拋出一个异常,通过处理异常,就能发现不安全的转换。


总结

1)强制类型转换一般不建议使用,因为会干扰系统的正常类型检查,很多异常转换本来编译器会报错的,但是一旦用了这些类型转换,就会抑制编译器的报错行为

2)有句话:使用reinterpret_cast很危险,而使用const_cast意味着设计有缺陷

 


 

 

参考资料:

https://blog.csdn.net/weixin_42203498/article/details/120288397

《C++强制类型转换运算符(static_cast、reinterpret_cast、const_cast和dynamic_cast)》

 

 

标签:类型转换,xxxx,reinterpret,int,C++,运算符,cast,转换,指针
来源: https://www.cnblogs.com/Brickert/p/16452362.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有