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

    结果:

  • 相关阅读:
    安卓开发之ListAdapter(二)
    两listview联动
    不要天真了,这些简历HR一看就知道你是培训的,质量不佳的那种
    天真!这简历一看就是包装过的
    一线城市为何难逃离,职场饭局正在“失宠”?
    腾讯架构师分享的Java程序员需要突破的技术要点
    百度最穷程序员现身,工作4年晒出存款后,网友:你是真穷!
    震惊微软!招程序员的流程居然...
    python基础认识(一)
    input修改placeholder文字颜色
  • 原文地址:https://www.cnblogs.com/yifengs/p/15178834.html
Copyright © 2011-2022 走看看