复盘 之 虚函数,多态

本文探讨了C++中的虚函数和多态性,强调了基类指针调用派生类重写虚函数的用途。虚表作为一个关键概念,存储了虚函数的入口地址,允许动态绑定。文章还指出,虚表内容在编译时确定,而动态绑定发生在运行时。此外,私有虚函数在多态情况下也可被基类指针调用,前提是派生类公开继承基类。
摘要由CSDN通过智能技术生成

麻了,昨天面试完才发现自己对虚函数,多态的知识理解的实在是太浅了…被问烂了…

建议大家看看这几篇文章:
虚函数及虚函数表

虚函数为什么效率低

为什么基类指针(或引用)可以调用派生类的private虚函数

下面是一些个人理解总结:

1. 首先我们搞清楚一个点,对于(基类指针指向派生类对象)到底有什么用?

Base *p = new Pai();
不是为了p能去使用派生类中的所有东西,p只能在实现多态时去调用派生类重写的虚函数,仅此而已!因为在编译的时候,编译器理解的就是p始终就是指向一个基类对象的,所以当我们在通过p去调用派生类中非动态的成员时,编译器报的错误是说:在基类中找不到成员。只有在运行时,这个基类指针才会动态的绑定到它被赋值的派生类上(比如在代码中是绑定到派生类),因此在通过基类指针调用虚函数时,使用的虚表指针是派生类对象的虚表指针(而不是基类对象的),从而去派生类的虚表里面找对于的虚函数,而在派生类的虚表中以及重写了(继承之后的地址偏移是一致的,但是重写后同样偏移地址上的函数被派生类的覆盖了),所以调用的就是派生类的!

关于虚函数,多态的细节真的非常多…

2.关于虚表的结构?以及虚表指针是如何寻址的?

虚表的结构就是一个类似数组的结构,但是没有那么简单,可以暂时这么理解;
虚表里面存放的就是虚函数们的入口地址(并不是函数),虚表就相当于是一个指针数组;
虚表指针就是指向虚表的指针,虚表指针和虚表的关系可以理解为:
int *vptr = new int[maxn];
vptr就相当于是虚表指针,[]就相当于是虚表;
那么这些虚表的内容都是在编译期间就确定的了,也就是我们相当于是知道了每个虚函数入口地址在虚表中的偏移量,所以我们在通过虚表指针访问虚函数的时候,不是遍历的找,而是类似于随机访问p->fun() <=> (*p->vptr[n]),n就是虚函数fun在虚表中的偏移量,是在编译阶段就确定了的。而动态是指,在运行的时候,绑定的是那个派生类,调用的是那个派生类的虚表指针。

3.虚表放的啥东西?

注意一个点,虚函数表中放的是函数的入口地址,所有函数只会保留一份;
别被网上说的误导了…在继承的时候,虚函数不会被继承多份,会被继承多份的是虚函数的入口地址!
看下面这张图:
在这里插入图片描述
下面是我自己画的:
单继承
图中1的地方是当派生类没有虚函数时的情况,其虚表指针直接指向基类的虚表就行;
多重继承

4.一个注意点。

如果要实现基类指针指向派生类对象,那么派生类一定要public继承基类,在私有继承和保护继承时基类指针(引用)无法指向派生类!

5.为什么在多态的时候,在类外,基类指针指向派生类时,基类指针能够调用到派生类重写的私有虚函数呢?

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值