虚函数表和虚函数指针

背景

虚函数表:它是一个虚函数地址的数组,一个类中可能有多个虚函数,这些虚函数会构成一个数组,虚函数表就是这个数组,记录虚函数地址,指向.text中具体代码的一个位置

作用:用来实现多态(一个接口不同形态):

        静态多态(编译期确定)

        动态多态(虚继承重写,运行时才确定调用哪个函数,基类指针指向的具体对象类型是子类还是基类?如果是基类,从基类虚函数表找函数指针;如果是子类,从子类虚函数表找函数指针


虚函数表创建前提   

编译过程中,发现某个类有virtual关键字,修饰的函数,会生成虚函数表

1、什么时候生成?

编译器编译的时候生成,发现virtua关键字修饰的函数

2、存放在哪里?

.o文件 磁盘中在只读数据段中(,rodata),运行当中只在只读代码区域里

.bss:未初始化的或者初始化为0的全局静态变量

.data:已初始化的全局、静态变量放在数据区

.rodata:只读数据段,虚函数表,运行时放在代码区(虚函数地址的数组)

运行时,.bss和.data会加载到静态存储区

虚函数表与虚函数指针的关系:

虚函数表指针就是指向虚函数表的指针

class A{
public:
    virtual void func();
};

这个类前面4个字节(32位,64位是8个字节)对应存储的是我们这个虚函数表指针(vptr),在堆区,vptr指向我们虚函数表地址,这个虚函数表(函数地址)数组里的指针,指着具体代码段中的地址

两者关系:

每个类只有一个虚函数表

vptr都是在堆上分配,指向的内容是一样的,地址肯定不一样(浅拷贝可能相同,共享一个指针(地址相同,释放有危险);深拷贝会在另外堆区开辟一个指针(地址不同),指向相同的虚函数表地址) 

类的不同对象,通常虚函数表的指针不一样的,拷贝构造或重载赋值运算符


虚函数表指针创建的时机:

1.类对象构造时,在构造函数时,编译器把类的虚函数表的地址赋给vptr

2.如果没有构造函数,类中有虚函数表,编译器会为类生成默认的构造函数,为这个类对象在堆前面生成8个字节指向虚函数表指针,构造函数的作用就是把类的虚函数表地址复制给我们的vptrv 

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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值