百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分析 > 正文

C++强制类型转换操作符 dynamic_cast

liebian365 2025-01-23 18:33 15 浏览 0 评论

dynamic_cast是四个强制类型转换操作符中最特殊的一个,它支持运行时识别指针或引用。

>>>>>>>>>>>编译器的RTTI设置>>>>>>>>>>>

dynamic_cast提供RTTI(Run-Time Type Information),也就是运行时类型识别。它对编译器有要求,需要编译器启动“运行时类型信息”这一选项。当编译器不开启RTTI时,运行含有dynamic_cast操作符的程序时会出现一个警告:

warning C4541: “dynamic_cast”用在了带 /GR- 的多态类型“ANIMAL”上;可能导致不可预知的行为

VS2010在默认下是开启RTTI的,也可以自己手动去开启或者关闭,操作如下:

视图->解决方案资源管理器
在打开的解决方案管理器中,对着项目名称右击,选择属性
配置属性-〉C/C++

>>>>>>>>>>>>>步入正题>>>>>>>>>>>>>

  • dynamic_cast主要用于“安全地向下转型”

dynamic_cast用于类继承层次间的指针或引用转换。主要还是用于执行“安全的向下转型(safe downcasting)”,也即是基类对象的指针或引用转换为同一继承层次的其他指针或引用。至于“先上转型”(即派生类指针或引用类型转换为其基类类型),本身就是安全的,尽管可以使用dynamic_cast进行转换,但这是没必要的, 普通的转换已经可以达到目的,毕竟使用dynamic_cast是需要开销的。

class Base
{
public:
    Base(){};
    virtual void Show(){cout<<"This is Base calss";}
};
class Derived:public Base
{
public:
    Derived(){};
    void Show(){cout<<"This is Derived class";}
};
int main()
{    
    Base *base ;
    Derived *der = new Derived;
    //base = dynamic_cast<Base*>(der); //正确,但不必要。
    base = der; //先上转换总是安全的
    base->Show(); 
    system("pause");
}

                                   学习交流群:894479708
                        欢迎所有初学和进阶者一起讨论学习!
  • dynamic_cast与继承层次的指针
  • 对于“向下转型”有两种情况。一种是基类指针所指对象是派生类类型的,这种转换是安全的;另一种是基类指针所指对象为基类类型,在这种情况下dynamic_cast在运行时做检查,转换失败,返回结果为0;

    #include "stdafx.h"
    #include<iostream>
    using namespace std;
    
    class Base
    {
    public:
        Base(){};
        virtual void Show(){cout<<"This is Base calss";}
    };
    class Derived:public Base
    {
    public:
        Derived(){};
        void Show(){cout<<"This is Derived class";}
    };
    int main()
    {    
        //这是第一种情况
        Base* base = new Derived;
        if(Derived *der= dynamic_cast<Derived*>(base))
        {
            cout<<"第一种情况转换成功"<<endl;
            der->Show();
            cout<<endl;
        }
        //这是第二种情况
        Base * base1 = new Base;
        if(Derived *der1 = dynamic_cast<Derived*>(base1))
        {
            cout<<"第二种情况转换成功"<<endl;
            der1->Show();
        }
        else 
        {
            cout<<"第二种情况转换失败"<<endl;
        }
    
                                                               学习交流群:894479708
                                                    欢迎所有初学和进阶者一起讨论学习!
      
        delete(base);
        delete(base1);
        system("pause");
    }

    运行结果:

          

    • dynamic_cast和引用类型

    在前面的例子中,使用了dynamic_cast将基类指针转换为派生类指针,也可以使用dynamic_cast将基类引用转换为派生类引用。

    同样的,引用的向上转换总是安全的:

        Derived c;
        Derived & der2= c;
        Base & base2= dynamic_cast<Base&>(der2);//向上转换,安全
        base2.Show();

    所以,在引用上,dynamic_cast依旧是常用于“安全的向下转型”。与指针一样,引用的向下转型也可以分为两种情况,与指针不同的是,并不存在空引用,所以引用的dynamic_cast检测失败时会抛出一个bad_cast异常:

    int main()
    {    
        //第一种情况,转换成功
        Derived b ;
        Base &base1= b;
        Derived &der1 = dynamic_cast<Derived&>(base1);
        cout<<"第一种情况:";
        der1.Show();
        cout<<endl;
    
        //第二种情况
        Base a ;
        Base &base = a ;
        cout<<"第二种情况:";
        try{
            Derived & der = dynamic_cast<Derived&>(base);
        }
        catch(bad_cast)
          
          
          
                                                               学习交流群:894479708
                                                    欢迎所有初学和进阶者一起讨论学习!
      
          
          
          
          
          
        {
            cout<<"转化失败,抛出bad_cast异常"<<endl;
        }
        system("pause");
    }

    运行结果:

    • 使用dynamic_cast转换的Base类至少带有一个虚函数

    当一个类中拥有至少一个虚函数的时候,编译器会为该类构建出一个虚函数表(virtual method table),虚函数表记录了虚函数的地址。如果该类派生了其他子类,且子类定义并实现了基类的虚函数,那么虚函数表会将该函数指向新的地址。虚表是C++多态实现的一个重要手段,也是dynamic_cast操作符转换能够进行的前提条件。当类没有虚函数表的时候(也即一个虚函数都没有定义),dynamic_cast无法使用RTTI,不能通过编译(个人猜想...有待验证)。

      当然,虚函数表的建立对效率是有一定影响的,构建虚函数表、由表查询函数 都需要时间和空间上的消耗。所以,除了必须声明virtual(对于一个多态基类而言),不要轻易使用virtual函数。对于虚函数的进一步了解,可以查看《Effective C++》





    获取更多:关注我 看我主页加入我们的学习大军!

    更多笔记,资料,教程 >>>>>>>> 私信 “资料” 获取

    相关推荐

    4万多吨豪华游轮遇险 竟是因为这个原因……

    (观察者网讯)4.7万吨豪华游轮搁浅,竟是因为油量太低?据观察者网此前报道,挪威游轮“维京天空”号上周六(23日)在挪威近海发生引擎故障搁浅。船上载有1300多人,其中28人受伤住院。经过数天的调...

    “菜鸟黑客”必用兵器之“渗透测试篇二”

    "菜鸟黑客"必用兵器之"渗透测试篇二"上篇文章主要针对伙伴们对"渗透测试"应该如何学习?"渗透测试"的基本流程?本篇文章继续上次的分享,接着介绍一下黑客们常用的渗透测试工具有哪些?以及用实验环境让大家...

    科幻春晚丨《震动羽翼说“Hello”》两万年星间飞行,探测器对地球的最终告白

    作者|藤井太洋译者|祝力新【编者按】2021年科幻春晚的最后一篇小说,来自大家喜爱的日本科幻作家藤井太洋。小说将视角放在一颗太空探测器上,延续了他一贯的浪漫风格。...

    麦子陪你做作业(二):KEGG通路数据库的正确打开姿势

    作者:麦子KEGG是通路数据库中最庞大的,涵盖基因组网络信息,主要注释基因的功能和调控关系。当我们选到了合适的候选分子,单变量研究也已做完,接着研究机制的时便可使用到它。你需要了解你的分子目前已有哪些...

    知存科技王绍迪:突破存储墙瓶颈,详解存算一体架构优势

    智东西(公众号:zhidxcom)编辑|韦世玮智东西6月5日消息,近日,在落幕不久的GTIC2021嵌入式AI创新峰会上,知存科技CEO王绍迪博士以《存算一体AI芯片:AIoT设备的算力新选择》...

    每日新闻播报(September 14)_每日新闻播报英文

    AnOscarstatuestandscoveredwithplasticduringpreparationsleadinguptothe87thAcademyAward...

    香港新巴城巴开放实时到站数据 供科技界研发使用

    中新网3月22日电据香港《明报》报道,香港特区政府致力推动智慧城市,鼓励公私营机构开放数据,以便科技界研发使用。香港运输署21日与新巴及城巴(两巴)公司签署谅解备忘录,两巴将于2019年第3季度,开...

    5款不容错过的APP: Red Bull Alert,Flipagram,WifiMapper

    本周有不少非常出色的app推出,鸵鸟电台做了一个小合集。亮相本周榜单的有WifiMapper's安卓版的app,其中包含了RedBull的一款新型闹钟,还有一款可爱的怪物主题益智游戏。一起来看看我...

    Qt动画效果展示_qt显示图片

    今天在这篇博文中,主要实践Qt动画,做一个实例来讲解Qt动画使用,其界面如下图所示(由于没有录制为gif动画图片,所以请各位下载查看效果):该程序使用应用程序单窗口,主窗口继承于QMainWindow...

    如何从0到1设计实现一门自己的脚本语言

    作者:dong...

    三年级语文上册 仿写句子 需要的直接下载打印吧

    描写秋天的好句好段1.秋天来了,山野变成了美丽的图画。苹果露出红红的脸庞,梨树挂起金黄的灯笼,高粱举起了燃烧的火把。大雁在天空一会儿写“人”字,一会儿写“一”字。2.花园里,菊花争奇斗艳,红的似火,粉...

    C++|那些一看就很简洁、优雅、经典的小代码段

    目录0等概率随机洗牌:1大小写转换2字符串复制...

    二年级上册语文必考句子仿写,家长打印,孩子照着练

    二年级上册语文必考句子仿写,家长打印,孩子照着练。具体如下:...

    一年级语文上 句子专项练习(可打印)

    ...

    亲自上阵!C++ 大佬深度“剧透”:C++26 将如何在代码生成上对抗 Rust?

    ...

    取消回复欢迎 发表评论: