解析
- 当父类中有了虚函数后,内部结构就发生了改变
- 内部多了一个 vfprt
- virtual function pointer 虚函数表指针
- 指向 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; }
结果: