zoukankan      html  css  js  c++  java
  • dynamic_cast 转换示例

    dynamic_cast 转换示例

    /*
    带虚函数与不带虚函数转换的区别
    
    dynamic_cast:必须要有虚函数才可以转换
    dynamic_cast:只能处理转换指针或引用,不能转换对象
    dynamic_case 只能识别多态数据类型,转换失败就是null
    多态,父类指针可以根据多态转化为子类指针
    子类指针存储一个父类指针,转换失败。指针为 00000
    子类指针转换成父类,自动转换
    
    typeid:自动识别类型,依赖于虚函数
    
    
    //虚函数重载和返回值无关 和参数的类型 个数 顺序有关
    //虚函数被继承下来了还是虚函数
    //如果要使用被继承的虚函数 不允许出现虚函数重载和覆盖
    //多态可以跨类 爷爷辈的指针 可以存储孙子辈的地址 父辈拔针的地址 
     */
    
    #include <iostream>
    
    /* 
    没有虚函数的情况下,子类同名函数会覆盖父类, 
    父类指针存储子类地址: 
                    1、有虚函数情况:调用子类方法 
                    2、没有虚函数情况:调用父类方法 
    */
    class base1
    {
    public:
        virtual void show()
        {
            std::cout << "base1->show()" << std::endl;
        }
    };
    
    class baseX: public base1
    {
    public:
        void show()
        {
            std::cout << "baseX->show()" << std::endl;
        }
    };
    
    class base2
    {
    public:
        void show()  // 注意: 不是虚函数
        {
            std::cout << "base2->show()" << std::endl;
        }
    };
    
    class baseY: public base2
    {
    public:
        void show()
        {
            std::cout << "baseY->show()" << std::endl;
        }
    };
    
    
    int main()
    {
        //多态,父类指针可以根据多态转化为子类指针  
        //子类指针存储一个父类指针,转换失败。指针为 0x00000000 
        base1 *p1 = new base1;
        base1 *p2 = new baseX;
        std::cout << "p1 addr: 0x" << p1 << " " << "p2 addr: 0x" << p2 << std::endl;
        p1->show();
        p2->show();
    
        //typeid:自动识别类型,依赖于虚函数
        std::cout << typeid(p2).name() << std::endl; // p1的类型为父类类型指针 class base1 *
        std::cout << typeid(*p2).name() << std::endl; // *p1的类型为子类类型 class baseX
    
        baseX *px = dynamic_cast<baseX *>(p1); // 使用子类指针存储一个父类指针
        std::cout << "px addr: 0x" << (void *)px << std::endl; // 转换失败,px的地址值为0x00000000
        // px->show(); // 可以通过编译,但是运行会崩溃
    
        base1 *pb1 = dynamic_cast<base1 *>(p2); // 使用父类指针存储一个子类指针
        std::cout << "pb1 addr: 0x" << (void *)pb1 << std::endl; // 转换成功
        pb1->show();
    
        std::cout << "===========================================" << std::endl;
    
        base2 *p3 = new base2;
        base2 *p4 = new baseY;
        std::cout << "p3 addr: 0x" << p3 << " " << "p4 addr: 0x" << p4 << std::endl;
        p3->show();
        p4->show();
    
        //typeid:自动识别类型,依赖于虚函数
        std::cout << typeid(p4).name() << std::endl; // p1的类型为父类类型指针 class base2 *
        std::cout << typeid(*p4).name() << std::endl; // *p1的类型为子类类型 class base2
    
        // 注意: 这里转换失败,是因为RTTI实时类型检测到p3和py的类型是不一样的,需要进行转换
        // 但是dynamic_cast转换只能识别多态数据类型,转换失败就是null
        // dynamic_cast:必须要有虚函数才可以转换
        //baseY *py = dynamic_cast<baseY *>(p3); // 使用子类指针存储一个父类指针
        //std::cout << "py addr: 0x" << (void *)py << std::endl; // 转换失败,px的地址值为0x00000000
        //px->show(); // 可以通过编译,但是运行会崩溃
    
        // 注意: 这里转换成功,是因为RTTI实时类型检测到p4和pb2的类型是一样的,无需转换,直接赋值即可
        base2 *pb2 = dynamic_cast<base2 *>(p4); // 使用父类指针存储一个父类指针
        std::cout << "pb2 addr: 0x" << (void *)pb2 << std::endl; // 转换成功
        pb2->show();
    
        //std::cout << "mytest" << std::endl;
        system("pause");
        return 0;
    }

    运行结果

  • 相关阅读:
    多个类定义attr属性重复的问题:Attribute "xxx" has already been defined
    好用的批量改名工具——文件批量改名工具V2.0 绿色版
    得到ImageView中drawable显示的区域的计算方法
    得到view坐标的各种方法
    实现类似于QQ空间相册的点击图片放大,再点后缩小回原来位置
    Material Designer的低版本兼容实现(五)—— ActivityOptionsCompat
    Android 自带图标库 android.R.drawable
    解决 Attempting to destroy the window while drawing!
    解决Using 1.7 requires compiling with Android 4.4 (KitKat); currently using API 4
    Material Designer的低版本兼容实现(四)—— ToolBar
  • 原文地址:https://www.cnblogs.com/lsgxeva/p/7693149.html
Copyright © 2011-2022 走看看