虚函数

本文探讨了虚函数在面向对象编程中的应用,通过代码示例展示了如何利用虚函数实现多态行为,揭示了虚函数在继承层次结构中动态绑定的关键作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

(如果你没有看过“Inside The C ++ Object Model”这本书,但又急切想知道,那你就应该从这里开始)
虚函数是如何做到因对象的不同而调用其相应的函数的呢?现在我们就来剖析虚函数。我们先定义两个类
1
2
3
4
6
7
8
9
10
class  A{ //虚函数示例代码
     public :
         virtual  void  fun(){cout<<1<<endl;}
         virtual  void  fun2(){cout<<2<<endl;}
};
class  B :  public  A{
     public :
         void  fun(){cout<<3<<endl;}
         void  fun2(){cout<<4<<endl;}
};
由于这两个类中有虚函数存在,所以 compile-器 就会为他们两个分别插入一段你不知道的数据,并为他们分别创建一个表。那段数据叫做vptr的 指针 ,指向那个表。那个表叫做VTBL,每个类都有自己的VTBL,VTBL的作用就是保存自己类中虚函数的地址,我们可以把VTBL地形象看成一个 数组 ,这个数组的每个元素存放的就是虚函数的地址,请看图
通过左图,可以看到这两个vtbl分别为class A和class B服务。现在有了这个模型之后,我们来分析下面的代码
A * p =新A;
P->乐趣();
毫无疑问,调用了A ::乐趣(),但是A ::乐趣()是如何被调用的呢?它像普通函数那样直接跳转到函数的代码处吗?不,其实是这样的,首先是取出的vptr的值,这个值就是vtbl中的地址,再根据这个值来到VTBL这里,由于调用的函数A ::乐趣()是第一个虚函数,所以取出的vtbl中第一个插槽的值即为第一个虚函数的地址(在不同的编译器下第一个VTBL布局不完全相同,在VS2008中第一个插槽的值为指向第一个虚函数的指针,而其他编译器中也可能出现第一个插槽中值为TYPE_INFO对象的指针),这个值就是A ::乐趣()的地址了,最后调用这个函数。现在我们可以看出来了,只要vptr的不同,指向的vtbl中就不同,而不同的VTBL里装着对应类的虚函数地址,所以这样虚函数就可以完成它的任务。
而对于class A和class B来说,他们的vptr 指针 存放在何处呢?其实这个指针就放在他们各自的实例对象里。由于class A和class B都没有 数据成员 ,所以他们的实例对象里就只有一个vptr的指针。通过上面的分析,现在我们来实作一段代码,来描述这个带有虚函数的类的简单模型
1
2
3
4
6
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值