天天看点

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;
}