zoukankan      html  css  js  c++  java
  • 多态原理

    解析

    • 当父类中有了虚函数后,内部结构就发生了改变
    • 内部多了一个 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;
    }

    结果:

  • 相关阅读:
    工作流flowable官方文档阅读笔记2
    bladex代码生成表单字典(非普通字典)改造
    bladex代码生成改造字典(表管理字段带入)
    bladex前端页面设置
    重链剖分
    CodeForces 311B
    洛谷 P6302
    AtCoder abc164_f
    ISIJ2020 不知道算不算游记
    AtCoder abc165
  • 原文地址:https://www.cnblogs.com/yifengs/p/15178834.html
Copyright © 2011-2022 走看看