BZ易风

导航

 

解析

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

结果:

 

posted on 2021-08-24 09:35  BZ易风  阅读(52)  评论(0编辑  收藏  举报