动态联编学习:三、虚函数表VTABLE

来源:互联网 发布:有线网络打印 编辑:程序博客网 时间:2024/05/12 17:51

 

      编译器在执行过程中遇到virtual关键字的时候,将自动安装动态联编需要的机制,首先为这些包含virtual函数的类(注意不是类的实例)--即使是祖先类包含虚函数而本身没有--建立一张虚拟函数表VTABLE。在这些虚拟函数表中,编译器将依次按照函数声明次序放置类的特定虚函数的地址。同时在每个带有虚函数的类中放置一个称之为vpointer的指针,简称vptr,这个指针指向这个类的VTABLE

      关于虚拟函数表,有几点必须声明清楚:

1. 每一个类别只能有一个虚拟函数表,如果该类没有虚拟函数,则不存在虚拟函数表。

2. C++编译时候编译器会在含有虚函数的类中加上一个指向虚拟函数表的指针vptr

3. 从一个类别诞生的每一个对象,将获取该类别中的vptr指针,这个指针同样指向类的VTABLE

因此类、对象、VTABLE的层次结构可以用下图表示。其中X类和Y类的对象的指针都指向了X,Y的虚拟函数表,同时X,Y类自身也包含了指向虚拟函数的指针。

 

      编译器在编译上面这段代码的时候将为这shapecircle两个对象分别建立一个VTABLE表,这些表依次填充派生类对象基类对象中声明的所有的虚函数地址。如果派生类本身没有重新定义基类的虚函数,那么填充的就是基类的虚函数地址。这样一旦如果函数调用一个派生类不存在的方法时候能够自动调用基类方法。然后编译器在每个类中放置一个vptr,一般置于对象的起始位置,继而在对象的构造函数中将vptr初始化为本类的VTABLE的地址。

 

C++ 编译程序时候按下面的步骤进行工作:

1)为各类建立虚拟函数表,如果没有虚函数则不建立。

2)暂时不连接虚函数,而是将各个虚函数的地址放入虚拟函数表中。

3)直接连接各静态函数。

 

 

      执行时候,诞生了oneshapecircleshape两个对象,oneshape对象的vptr指针指向shapeVTABLEcircleshape对象的vptr指针指向circleshapeVTABLE,在执行oneshape.fun()的时候,fun函数的this指针指向了oneshape对象,进入fun()之后程序继续执行this->draw(),由于this指向oneshape对象,oneshapevptr又指向shape类的VTABLE,这样就从VTABLE中得到需要绑定的函数的地址,并连接起来。同样,this-> area()也经由oneshape对象而连接到相应的函数上,如图。

 

      现在我们执行baseshape.fun()。

 

      函数进入fun函数之后,函数的this指针将指向basefun对象,另一方面basefun指向一个circleshape,因此this指针指向的实际上为circleshape对象,而circleshapevptr指针指向circle类的虚拟函数表,这样编译器将从虚拟表中取出circle::draw()circle::area()的地址,进行连接。因为circle本身没有重新定义area()方法,因此编译器使用shapearea()方法。如图:

 

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 在火车上肚子疼怎么办 户口是学签证怎么办 学生去韩国护照怎么办 户口迁移原护照怎么办 考科四档案丢了怎么办 驾照档案袋丢了怎么办 驾照考试档案丢失怎么办 驾校不给档案怎么办 学员卡丢了怎么办 第一次办身份证急用怎么办 医保卡没有磁性怎么办 退休后大病医保怎么办 退休了医保不够怎么办 社保采集信息后怎么办 医保卡个人欠费怎么办 离婚房产不过户怎么办 科目四五次不过怎么办 科二考试下雨怎么办 科目三无法超车怎么办 下雨天考科目二怎么办 考科二下雨对点怎么办 上海自考准考证过期怎么办 驾照到年龄后怎么办 科三考试约不上怎么办 科目四预约不了怎么办 科目三考试迟到怎么办 科目四无法预约怎么办 新车换年检标志怎么办 科目一二次不过怎么办 科目一两次不过怎么办 考科目一没考过怎么办 科目一挂了怎么办 科目一考试不及格怎么办 科二考试不合格怎么办 驾校没给档案怎么办 考科目一没带身份证怎么办 企业经营期限届满怎么办 网上买票待核验怎么办 手机购票待审核怎么办 护士注册过期了怎么办 驾照已经过期了怎么办