虚函数表与动态绑定

虚函数表与动态绑定

一.单继承虚表模型

•包含虚函数的类

class B 
 { 
    virtual int f1 (void); 
    virtual void f2 (int); 
    virtual int f3 (int); 
 };

•编译器会为每个包含虚函数的类生成一张虚函数表,即存放每个虚函数地址的函数指针数组,简称虚表(vtbl),每个虚函数对应一个虚函数表中的索引号
–0 -> B::f1
1 -> B::f2
2 -> B::f3

除了为包含虚函数的类生成虚函数表以外,编译器还会为该类增加一个隐式的成员变量,
通常在该类实例化对象的起始位置,用于存放虚函数表的首地址,该变量被称为虚函数表指针,简称虚指针(vptr)

•代码:B* pb = new B;
pb->f3 (12);
将被编译为:pb->vptr[2] (pb, 12); // B::f3
调用对象的地址被做为this指针,传递给成员函数的第一个(看不见的)形参

•虚表是一个类一张,而不是一个对象一张,同一个类的多个对象,通过各自的虚指针,共享同一张虚表

•继承自B的子类

–class D : public B
{
int f1 (void);
int f3 (int);
virtual void f4 (void);
};

•子类覆盖了基类的f1和f3,继承了基类的f2,增加了自己的f4,编译器同样会为子类生成一张专属于它的虚表

–0 -> D::f1
1 -> B::f2
2 -> D::f3
3 -> D::f4

•指向子类虚表的虚指针就存放在子类对象的基类子对象中,通常在起始位置

•代码: B* pb = new D; pb->f3 (12);

被编译为: pb->vptr[2] (pb, 12); // D::f3
而这就是所谓的多态

二.何为动态绑定

•当编译器看到通过指针或引用调用虚函数的语句时,并不急于生成有关函数调用的指令,相反它会用一段代码替代该语句,这段代码在运行时被执行,完成如下操作

1.确定调用指针或引用的目标对象的真实类型

2.从调用指针或引用的目标对象中找到虚函数表,并从虚函数表中获取所调用虚函数的入口地址

3.根据入口地址,调用该函数

三.动态绑定对性能的影响

•虚函数表本身会增加内存空间的开销

•与普通函数调用相比,虚函数调用要多出几个步骤,增加运行时间的开销

•动态绑定会妨碍编译器通过内联来优化代码

•只有在确实需要多态特性的场合才使用虚函数,否则尽量使用普通函数

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值