多态(虚函数、纯虚函数、虚函数表)

1. 虚函数与纯虚函数

实现多态

多态包括:

静态多态(编译时)

通过函数重载(同一个作用域内,可以有同名的不同的参数列表)和运算符重载

编译时确定了要调用的函数,调用效率高
动态多态(运行时)通过函数重写和虚函数(派生类可以重写基类的虚函数)。同一个函数调用时可以有不同的行为

纯虚函数(在函数申明末尾加上=0)vs虚函数:

  1. 实现性:纯虚函数没有实现(没有函数体,只有申明),而虚函数可以有实现。
  2. 抽象性:包含纯虚函数的类是抽象类,不能直接实例化;而包含虚函数的类不一定是抽象类,可以实例化。
  3. 强制性:派生类必须重写纯虚函数才能实例化;而虚函数的重写是可选的。

也就是说:纯虚函数要求派生类必须重写纯虚函数才能实例化,但是虚函数可以选择不重写虚函数,因此可以定义清晰的接口,保持代码的一致性,统一设计模式的通用接口

2. 虚函数表:

创建时机:编译器编译的时候生成,virtual 关键字修饰的函数

存放位置:分:可执行程序(磁盘)、运行状态(内存)

              (磁盘中的形态:

                            包括:存储.bss 静态变量、未初始化的或初始化为0的全局变量

                            .data 已经初始化的全局、静态变量

                            .rodata readonly 只读数据段里面放虚函数表

)         

转到运行状态(内存)包括:

内核空间,栈区,文件映射区,堆区,数据区(静态存储区),代码区

虚函数表是虚函数地址的数组,指向代码区中的地方

3. 虚函数表和虚函数表指针的关系

虚函数表:class 类,指针数组,每个元素指向一个虚函数的实现。包含了一个类中所有虚函数的指针,包括从基类继承的虚函数和派生类中新添加或重写的虚函数。这种机制确保了多态性的实现,即在运行时根据对象的实际类型调用正确的函数实现。

虚函数表指针:对象中,存储在对象中的指针vptr,指向该对象所属类的虚函数表,就是指向虚函数表的指针

问题:一个类如果创建了不同的对象,那么它们的虚函数表指针内容一样吗?

vptr在内存的位置不一样(浅拷贝,危险!!!不同对象vptr共享同一片内存,一个vptr变成null会影响其他的 和深拷贝,重新分配新内存,不会影响),但是指向的地址是一样的(都是指向类的虚函数表,也就是会共享相同的虚函数表指针内容)建议进行深拷贝

4. 虚函数表指针的创建时间:

new:先调用operate,再分配内存空间,再析构函数

1) 类对象构造的时候,将类的虚函数表指针赋值给vptr

2) 如果类没有构造函数,编译器会生成默认的构造函数

3) 继承情况下,虚函数表指针的赋值过程:

   a. 调用基类的构造函数,会将基类的虚函数表的地址赋值给vptr

   b. 调用子类构造函数,将子类的虚函数表的地址赋值给vptr

  1. 基类构造函数:当一个派生类对象被构造时,首先会调用其基类的构造函数(按照继承链从最顶层的基类开始)。在基类构造函数中,对象的 vptr 会被初始化为指向基类的虚函数表。这是因为在派生类构造函数执行之前,对象首先需要作为基类类型的实体存在。

  2. 派生类构造函数:随后,当执行到派生类的构造函数时,如果派生类有自己的虚函数表(通常是因为派生类重写了基类的虚函数或添加了新的虚函数),则对象的 vptr 会被更新为指向派生类的虚函数表。这个过程确保了通过基类指针或引用访问派生类对象时,能够调用到派生类中的正确虚函数实现

动态绑定

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值