指向派生类的基类指针、强转为 void* 再转为基类指针、此时调用虚函数会发生什么?
1、无论指针类型怎么转,类对象内存没有发生任何变化,还是vfptr指向虚函数表,下面是成员变量,这在编译阶段就已经确定好了;
2、运行时,会根据vfptr找到vftable,然后确定类型为派生类(RTTI运行时类型识别),这是调用虚函数是查表来调用的,在编译的时候派生类的虚函数早就把基类的虚函数给覆盖了,调用的肯定是派生类的虚函数
3、整个调用过程如下
编译器进行编译成汇编代码时,先看到show函数,show函数是虚函数,虚函数编译时就不能直接call show了,而是通过vfptr找到虚函数表,大概过程如下
mov ecx dword ptr[p3] //找到vfptr
mov eax dword ptr[ecx] //把vfptr指向的地址,也就是vftable[0]的地址给寄存器eax,eax里存放的是派生类show函数的地址
call eax //调用派生类的show
以上三句汇编才是虚函数产生多态的核心
#include <iostream>
#include <memory>
#include<iostream>
using namespace std;
//基类
class Base
{
public:
virtual void show()
{
cout << "base ::show" << endl;
}
public:
int ma;
};
class Derived:public Base
{
public:
virtual void show()
{
cout << "Derived ::show" << endl;
}
public:
int mb;
};
int main()
{
Base* p1 = new Derived;
p1->show();
void* p2 = (void*)p1;
Base* p3 = (Base*)p2;
p3->show();
return 0; ;
}