当前位置: 首页 > news >正文

C++------static_cast和dynamic_cast详解

这里写自定义目录标题


类继承关系图
在这里插入图片描述

注:从图中可以看出,派生类不仅有自己的方法和属性,同时它还包括从父类继承来的方法和属性。当我们从派生类向基类转换时,不管用传统的c语言还是c++转换方式都可以百分百转换成功。但是可怕是向下转换类型,也就是我们从基类向派生类转换,当我们采用传统的C语言和c++转换时,就会出现意想不到的情况,因为转换后派生类自己的方法和属性丢失了,一旦我们去调用派生类的方法和属性那就糟糕了,这就是对类继承关系和内存分配理解不清晰导致的。好在c++增加了static_cast和dynamic_cast运用于继承关系类间的强制转化

一、static_cast和dynamic_cast使用方式

static_cast< new_type>(expression) 
dynamic_cast<new_type>(expression)  
备注:new_type为目标数据类型,expression为原始数据类型变量或者表达式。  

二、static_cast详解:

static_cast相当于传统的C语言里的强制转换,该运算符把expression转换为new_type类型,用来强迫隐式转换如non-const对象转为const对象,编译时检查,用于非多态的转换,可以转换指针及其他,但没有运行时类型检查来保证转换的安全性。它主要有如下几种用法:

①用于类层次结构中基类(父类)和派生类(子类)之间指针或引用的转换。 进行上行转换(把派生类的指针或引用转换成基类表示)是安全的; 进行下行转换(把基类指针或引用转换成派生类表示)时,由于没有动态类型检查,所以是不安全的。
②用于基本数据类型之间的转换,如把int转换成char,把int转换成enum。
③把空指针转换成目标类型的空指针。
④把任何类型的表达式转换成void类型。
注意:static_cast不能转换掉expression的const、volatile、或者__unaligned属性

基本类型数据转换举例如下:

char a = 'a';
int b = static_cast<char>(a);//正确,将char型数据转换成int型数据double *c = new double;
void *d = static_cast<void*>(c);//正确,将double指针转换成void指针int e = 10;
const int f = static_cast<constint>(e);//正确,将int型数据转换成const int型数据const int g = 20;
int *h = static_cast<int*>(&g);//编译错误,static_cast不能转换掉g的const属性类上行和下行转换: 
class Base
{};class Derived : public Base
{}Base* pB = new Base();
if(Derived* pD = static_cast<Derived*>(pB))
{}//下行转换是不安全的(坚决抵制这种方法)Derived* pD = new Derived();
if(Base* pB = static_cast<Base*>(pD))
{}//上行转换是安全的

三、dynamic_cast详解:

转换方式: dynamic_cast< type*>(e)
type必须是一个类类型且必须是一个有效的指针 dynamic_cast< type&>(e)
type必须是一个类类型且必须是一个左值 dynamic_cast<type&& >(e)
type必须是一个类类型且必须是一个右值

e的类型必须符合以下三个条件中的任何一个:
1、e的类型是目标类型type的公有派生类
2、e的类型是目标type的共有基类
3、e的类型就是目标type的类型。

如果一条dynamic_cast语句的转换目标是指针类型并且失败了,则结果为0。如果转换目标是引用类型并且失败了,则dynamic_cast运算符将抛出一个std::bad_cast异常(该异常定义在typeinfo标准库头文件中)。e也可以是一个空指针,结果是所需类型的空指针。

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

在类层次间进行上行转换时,dynamic_cast和static_cast的效果是一样的;在进行下行转换时,dynamic_cast具有类型检查的功能,比static_cast更安全。dynamic_cast是唯一无法由旧式语法执行的动作,也是唯一可能耗费重大运行成本的转型动作。

(1)指针类型 举例,Base为包含至少一个虚函数的基类,Derived是Base的共有派生类,如果有一个指向Base的指针bp,我们可以在运行时将它转换成指向Derived的指针,代码如下:

if(Derived *dp = dynamic_cast<Derived*>(bp))
{//使用dp指向的Derived对象  
}
else
{//使用bp指向的Base对象  
} 

值得注意的是,在上述代码中,if语句中定义了dp,这样做的好处是可以在一个操作中同时完成类型转换和条件检查两项任务。

(2)引用类型

因为不存在所谓空引用,所以引用类型的dynamic_cast转换与指针类型不同,在引用转换失败时,会抛出std::bad_cast异常,该异常定义在头文件typeinfo中。

void f(const Base &b)
{try{const Derived &d = dynamic_cast<const Base &>(b);  //使用b引用的Derived对象}catch(std::bad_cast){//处理类型转换失败的情况}
} 

四、转换注意事项:

尽量少使用转型操作,尤其是dynamic_cast,耗时较高,会导致性能的下降,尽量使用其他方法替代。

http://www.xdnf.cn/news/827227.html

相关文章:

  • HTML网页制作知识总结(简单易学)
  • 【建议收藏】Windows批处理(cmd/bat)常用命令总结
  • ubuntu下安装jdk
  • 关于代码评审(CodeReview)那些不得不说的事儿
  • 10大办公常用工具\网址分享(收藏一波)
  • 都2023了还不知道怎么GCC,今天就来教大家如何安装GCC
  • 关于代码混淆,看这篇就够了
  • 决策树模型
  • JAVA DecimalFormat 保留小数位以及四舍五入的陷阱
  • 了解Beamforming
  • 卡巴斯基 注册码
  • JAVA中的API文档
  • SDK、API、Open API有什么区别(iot开发平台)
  • HBase之Compaction
  • 内网IP如何查看?
  • Fiddler4使用教程
  • 【全网】Nginx最全使用教程
  • linux环境下载文件
  • Oracle如何新建用户
  • 《深入浅出Dart》Flutter中的Material和Cupertino组件
  • java中异常详解以及运行时异常runtime exception
  • mySQL常见命令
  • Nature综述:肠道菌群如何划分肠型
  • 基于Protege的知识建模实战
  • 树莓派笔记5:自制小车(简单避障)
  • SQL Server 2012 下载和安装详细教程
  • 线程池之ScheduledThreadPoolExecutor详解
  • System.currentTimeMillis()与SystemClock.uptimeMillis()
  • JavaBean技术
  • Robots协议(爬虫协议、机器人协议)