基类对象的指针或者引用调用虚函数时,都以多态的流程执行代码。可以说,虚函数就是为实现多态做准备的。
同一个类的不同对象,共用同一个虚函数表,且虚函数表最可能存放在常量区/代码段
修饰函数:表明该函数不能被重写。
修饰类:表明该类不能被继承
检查派生类虚函数是否重写了基类某个虚函数,如果没有重写编译报错
class A
{
public:
virtual void func(int val = 1){ std::cout<<"A->"<< val <"<< val <test();
return 0;
}
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-g5kphQjE-1660721146365)(./%E5%A4%9A%E6%80%81.assets/image-20220817095135938-16607010973161.png)]](https://1000bd.com/contentImg/2022/08/19/064733818.png)
不同的子类对象,通过基类指针与引用,调用相同的函数,产生不同的效果。

通过基类对象的指针或者引用,调用虚函数,且该虚函数完成重写时,构成多态。
通过设置一个虚函数表,实现多态

class Base {
public:
virtual void func1() { cout << "Base1::func1" << endl; }
virtual void func2() { cout << "Base1::func2" << endl; }
private:
int b1;
};
class Derive : public Base {
public:
virtual void func1() { cout << "Derive::func1" << endl; }
virtual void func3() { cout << "Derive::func3" << endl; }
private:
int d1;
};
//typedef void(*) () VFPTR;
//本来重命名函数指针类型时是这样,但是C++语言规定这种是不行的,需要将VFPTR放到内部
typedef void(*VFPTR) ();
void PrintVTable(VFPTR vTable[])
{
cout << " 虚表地址>" << vTable << endl;
for (int i = 0; vTable[i] != nullptr;++i)
{
printf("第%d个虚函数地址 :%p,->", i, vTable[i]);
//通过this调用函数是在编译阶段的事情,一旦到内存就没有这种限制
VFPTR f = vTable[i];
f();
}
cout << endl;
}
int main()
{
Derive d;
printf("Derive::func1地址%p\n", &(Derive::func1));
printf("Derive::func2地址%p\n", &(Derive::func2));
printf("Derive::func3地址%p\n", &(Derive::func3));
VFPTR* vTableb1 = (VFPTR*)(*((void**)&d));
//通过强制转换来获得d中前一个指针大小的字节内容。
//考虑到不同平台指针大小不同,
//我们指针指针解引用后会得到对应地址后的指向对象大小的内容
// 即int *p,p解引用后,得到从指向对象地址也就是变量p中的值
// 开始的sizeof(int)字节大小的内容
//
// 因此将d的地址强转为二级指针,当引用后,
// 就可以的到对应地址的sizeof(void*)大小的内容
// 就可以满足不同平台完成同样的需求
//最后再强制转换即可
PrintVTable(vTableb1);
}

可以发现,主动打印的函数地址和虚函数表中的地址是不同?
这是因为VS进行了封装,无论是主动打印的还是虚函数表中的地址都不是真正的函数地址,而是一个指令地址。证明如下

实际中我们不建议设计出菱形继承及菱形虚拟继承,一方面太复杂容易出问题,另一方面这样的模型,访问基类成员有一定得性能损耗。所以菱形继承、菱形虚拟继承我们的虚表我们就不看了,一般我们也不需要研究清楚,因为实际中很少用。如果好奇心比较强的宝宝,可以去看下面的两篇链接文章。
在发生代码冗余与二义性的地方,通过virtual继承,建立一个虚基表,通过相对偏移量实现基类的共享
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nxFYnksm-1660721146387)(./%E5%A4%9A%E6%80%81.assets/image-20220817151052587-166072025699917.png)]](https://1000bd.com/contentImg/2022/08/19/064734605.png)