C++中4种强制类型转换的区别详析

 更新时间:2021年03月05日 14:18:45   作者:制造天堂  
这篇文章主要给大家介绍了关于C++中4种强制类型转换区别的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

前言

C++即支持C风格的类型转换,又有自己风格的类型转换。C风格的转换格式很简单,但是有不少缺点的:

  1.转换太过随意,可以在任意类型之间转换。你可以把一个指向const对象的指针转换成指向非const对象的指针,把一个指向基类对象的指针转换成一个派生类对象的指针,这些转换之间的差距是非常巨大的,但是传统的C语言风格的类型转换没有区分这些。

  2.C风格的转换没有统一的关键字和标示符。对于大型系统,做代码排查时容易遗漏和忽略。

  C++风格完美的解决了上面两个问题。1.对类型转换做了细分,提供了四种不同类型转换,以支持不同需求的转换;2.类型转换有了统一的标示符,利于代码排查和检视。下面分别来介绍这四种转换:static_cast、dynamic_cast、const_cast和reinterpre_cast.

一、static_cast转换

  1.基本用法:static_cast<type-id> expression

  2.使用场景:

  a、用于类层次结构中基类和派生类之间指针或引用的转换

  上行转换(派生类---->基类)是安全的;

  下行转换(基类---->派生类)由于没有动态类型检查,所以是不安全的。

  b、用于基本数据类型之间的转换,如把int转换为char,这种带来安全性问题由程序员来保证

  c、把空指针转换成目标类型的空指针

  d、把任何类型的表达式转为void类型

  3.使用特点

  a、主要执行非多态的转换操作,用于代替C中通常的转换操作

  b、隐式转换都建议使用static_cast进行标明和替换

二、dynamic_cast转换

  1.基本用法:dynamic_cast<type-id> expression

  2.使用场景:只有在派生类之间转换时才使用dynamic_cast,type-id必须是类指针,类引用或者void*。

  3.使用特点:

  a、基类必须要有虚函数,因为dynamic_cast是运行时类型检查,需要运行时类型信息,而这个信息是存储在类的虚函数表中,只有一个类定义了虚函数,才会有虚函数表(如果一个类没有虚函数,那么一般意义上,这个类的设计者也不想它成为一个基类)。

  b、对于下行转换,dynamic_cast是安全的(当类型不一致时,转换过来的是空指针),而static_cast是不安全的(当类型不一致时,转换过来的是错误意义的指针,可能造成踩内存,非法访问等各种问题)

  c、dynamic_cast还可以进行交叉转换

三、const_cast转换

  1.基本用法:const_cast<type-id>expression

  2.使用场景:

  a、常量指针转换为非常量指针,并且仍然指向原来的对象

  b、常量引用被转换为非常量引用,并且仍然指向原来的对象

  3.使用特点:

  a、cosnt_cast是四种类型转换符中唯一可以对常量进行操作的转换符

  b、去除常量性是一个危险的动作,尽量避免使用。一个特定的场景是:类通过const提供重载时,一般都是非常量函数调用const_cast<const T>将参数转换为常量,然后调用常量函数,然后得到结果再调用const_cast <T>去除常量性。

四、reinterpret_cast转换

  1.基本用法:reinterpret_cast<type-id>expression

  2.使用场景:不到万不得已,不用使用这个转换符,高危操作

  3.使用特点:  

  a、reinterpret_cast是从底层对数据进行重新解释,依赖具体的平台,可移植性差

  b、reinterpret_cast可以将整型转换为指针,也可以把指针转换为数组

  c、reinterpret_cast可以在指针和引用里进行肆无忌惮的转换

五、各种转换之间的比较

  1.static_cast和dynamic_cast

class Base
{
 public:
 Base(int c = 2):_c(c){}
 public:
 int _c;
};
class Derived:public Base
{
 public:
 int _d;
 int _e;
};
int main(void)
{
 int tempA = 2;
 int tempB = 3;
 Base base;
 
 /*1.无编译告警,但是危险操作,譬如说调用drvPtrA->_d会造成不可预知的后果*/
 Derived *drvPtrA = static_cast<Derived *>(&base);
 
 drvPtrA->_d = 4;
 drvPtrA->_e = 5;
 /*2.输出:tempA为5,tempB为4,踩内存了(机器信息:32位ubuntu,编译器clang++)*/
 cout<<tempA<<endl;
 cout<<tempB<<endl;
 
 /*3.Base中没有虚函数,无法查看运行时信息,编译不过*/
 Derived *drvPtrB = dynamic_cast<Derived *>(base);

 return 0;
}

  在基类派生类互相转换时,虽然static_cast是在编译期完成,效率更高,但是不安全,上例中就示范了一个踩内存的例子。相比之下因为dynamic_cast可以查看运行时信息,上例如果Base含有虚函数,那么drvPtrB就是一个空指针(这可比踩内存什么的好多了),不能操作Derived中_d的数据从而保证安全性,所以应该优先使用dynamic_cast。

  2.static_cast和reinterpret_cast

class BaseA
{
 public:
 BaseA(int c = 2):_c(c){}
 int _c;
};
class BaseB
{
 public:
 BaseB(int d = 3):_d(d){}
 int _d;
};
int main(void)
{
 BaseA baseA;
 /*1.编译不过*/
 BaseB *baseB = static_cast<BaseB *>(&baseA);
 /*2.无任何编译告警,编译通过,正常运行*/
 BaseB *baseC = reinterpret_cast<BaseB *>(&baseA);
 cout<<baseC->_d<<endl;

 return 0;
}

  static_cast虽然也不是一种绝对安全的转换,但是它在转换时,还是会进行必要的检测(诸如指针越界计算,类型检查)。reinterpret_cast完全是肆无忌惮,直接从二进制开始重新映射解释,是极度不安全的,再次提醒,不到万不得已,不要使用。

总结

到此这篇关于C++中4种强制类型转换区别的文章就介绍到这了,更多相关C++强制类型转换区别内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C语言中不定参数 ... 的语法以及函数封装

    C语言中不定参数 ... 的语法以及函数封装

    不定参数是指函数可以接收不确定个数的参数,下面这篇文章主要给大家介绍了关于C语言中不定参数 ... 的语法以及函数封装的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2023-01-01
  • C语言实现密码本

    C语言实现密码本

    这篇文章主要为大家详细介绍了C语言实现密码本,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-02-02
  • OpenCV实现轮廓的发现

    OpenCV实现轮廓的发现

    这篇文章主要为大家详细介绍了OpenCV如何实现轮廓的发现,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-05-05
  • C语言实现运筹学中的马氏决策算法实例

    C语言实现运筹学中的马氏决策算法实例

    这篇文章主要介绍了C语言实现运筹学中的马氏决策算法,简单介绍了马氏决策的概念,并结合实例形式分析了C语言实现马氏决策算法的具体实现技巧,需要的朋友可以参考下
    2017-09-09
  • C++实现LeetCode(125.验证回文字符串)

    C++实现LeetCode(125.验证回文字符串)

    这篇文章主要介绍了C++实现LeetCode(验证回文字符串).本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-07-07
  • C语言逆向分析语法超详细分析

    C语言逆向分析语法超详细分析

    这篇文章主要介绍了C语言逆向分析语法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧
    2022-11-11
  • 如何为Qt视图中的文字实现彩虹渐变效果

    如何为Qt视图中的文字实现彩虹渐变效果

    这篇文章主要给大家介绍了关于如何为Qt视图中的文字实现彩虹渐变效果的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者使用Qt具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-03-03
  • C语言 指针变量作为函数参数详解

    C语言 指针变量作为函数参数详解

    本文主要介绍C语言 指针变量作为函数参数,这里整理了相关资料和示例代码,以便大家学习参考理解知识点,有需要的小伙伴可以参考下
    2016-08-08
  • 详解如何用alpine镜像做一个最小的镜像并运行c++程序

    详解如何用alpine镜像做一个最小的镜像并运行c++程序

    这篇文章主要介绍了详解如何用alpine镜像做一个最小的镜像并运行c++程序,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-10-10
  • 详解C++11中模板的优化问题

    详解C++11中模板的优化问题

    这篇文章主要介绍了C++11中模板的优化问题,通过实例代码得出结论,当所有模板参数都有默认参数时,函数模板的调用如同一个普通函数,具体示例代码跟随小编一起看看吧
    2021-09-09

最新评论