• 多态原理


    解析

    • 当父类中有了虚函数后,内部结构就发生了改变
    • 内部多了一个 vfprt
    1.  virtual  function pointer 虚函数表指针
    2.  指向 vftable  虚函数表
    • 父类中结构  vfptr     &Animal::speak
    • 子类中 进行继承 会继承 vfptr  vftable
    • 构造函数中 会将虚函数表指针 指向自己的虚函数表
    • 如果发生了重写,会替换掉虚函数表中的原有的speak,改为 &Cat::speak
    • 深入剖析,内部到底如何调用
    • ((void(*)())  (*(int*)*(int*)animal))();
    • 猫吃鱼的函数调用(编译器的调用)

    基类数据类型

    派生类

    实例:

    #define _CRT_SECURE_NO_WARNINGS
    #include <iostream>
    using namespace std;
    
    class Animal
    {
    public:
        virtual void speak()
        {
            cout << "动物在说话" << endl;
        }
    };
    class Cat:public Animal
    {
    public:
        void speak()
        {
            cout << "喵喵。。。" << endl;
        }
    };
    void doSpeak(Animal& animal)  //Animal & animal = cat
    {
        animal.speak();
    }
    void test01()
    {
        //父类指针指向子类对象  多态
        Animal* animal = new Cat;
        //animal->speak();
    
        //*(int*)animal 取到cat的虚函数表
        //(int*)*(int*)animal  虚函数表是数组结构 数组类型是int 需要加int*强转成数组
        //*(int*)*(int*)animal  取*获取函数
        //void(*)()     取函数指针
        // ((void(*)())  (*(int*)*(int*)animal))  合并
        //相当于 animal->speak   调用需加()
        ((void(*)())  (*(int*)*(int*)animal))(); //调用函数
    }
    
    int main()
    {
        test01();
        system("Pause");
        return 0;
    }

    结果:

    吃鱼:

    #define _CRT_SECURE_NO_WARNINGS
    #include <iostream>
    using namespace std;
    
    class Animal
    {
    public:
        virtual void speak()
        {
            cout << "动物在说话" << endl;
        }
        virtual void eat()
        {
            cout << "动物在干饭" << endl;
        }
    };
    class Cat:public Animal
    {
    public:
        void speak()
        {
            cout << "喵喵。。。" << endl;
        }
        void eat()
        {
            cout << "小猫在吃鱼" << endl;
        }
    };
    void doSpeak(Animal& animal)  //Animal & animal = cat
    {
        animal.speak();
    }
    void test01()
    {
        //父类指针指向子类对象  多态
        Animal* animal = new Cat;
        //animal->speak();
    
        //(int*)animal  取到指向cat的虚拟函数表的vfptr指针
        //*(int*)animal 取到cat的虚函数表
        //(int*)*(int*)animal  虚函数表是数组结构 数组类型是int 需要加int*强转成数组的地址
        //*(int*)*(int*)animal  取*获取函数
        //void(*)()     取函数指针
        // ((void(*)())  (*(int*)*(int*)animal))  合并
        //相当于 animal->speak   调用需加()
        ((void(*)())  (*(int*)*(int*)animal))(); //调用函数
    
        //吃鱼
        //(int*)animal  取到指向cat的虚拟函数表的vfptr指针
        //*(int*)animal 取到cat的虚函数表
        //(int*)*(int*)animal  虚函数表是数组结构 数组类型是int 需要加int*强转成数组的地址
        // (int*)*(int*)animal + 1 获取到数组的第1位的地址
        // *((int*)*(int*)animal + 1)  获取到吃鱼的函数
        ((void(*)())  (*((int*)*(int*)animal + 1)))(); //调用函数
    }
    
    int main()
    {
        test01();
        system("Pause");
        return 0;
    }

    结果:

  • 相关阅读:
    [转].net mvc + vuejs 的项目结构
    Outlook IMAP 修改PST文件存储路径
    VS2017 性能优化方法
    查询存储过程所需参数
    如何保障微服务架构下的数据一致性
    sqlserver批量给用户配置存储过程权限
    vue中刷新当前页面或重新加载的两种方法
    vue history模式下的微信支付,及微信支付授权目录的填写,处理URL未注册
    Vue 四行代码实现无感知上拉加载更多
    2019年前端必用正则(js)
  • 原文地址:https://www.cnblogs.com/yifengs/p/15178834.html
Copyright © 2020-2023  润新知