热门问题
时间线
聊天
视角

虚拟方法表

来自维基百科,自由的百科全书

Remove ads

程序设计中的虚拟方法表(virtual method table)、虚函数表(virtual function table)或vtable,是一种编程语言里支持动态分派(在运行时英语Run time (program lifecycle phase)进行方式绑定)的方式。

若有类别定义了虚函数(或虚方法),大部分的编译器会在此类中加入隐藏成员变量,此变量是一个指向函数数组(即为虚拟方法表)指针。在程序运行时会使用此指针,调用适当的函数实现,在编译时,还不知道要调用哪一个函数,或是要调用某个继承此类别的类别所实现的函数。

要实现动态分派的方式有很多种,但在C++以及其他相关语言(如D语言C#)里常会使用虚拟方法表。一些将对象的程序接口和其实现分开的语言,像是Visual BasicDelphi,也常使用此一作法,因为此作法可以让对象用设置另一个方法指针的方式,就可以使用不同的函数实现。此作法可以创建外部的函数库,其他类似的技术则不行[1]

假设程序中包括三个有继承关系的类别:母类别Cat,以及二个子类HouseCatLionCat类定义了虚函数,名称为speak,其子类可以提供适当的实现(例如meowroar)。当程序调用Cat参考(指向CatHouseCatLion的个体),程序必须要可以确认要调用哪一函数。这会依对象实际的类别而定,不是参考本身的类别。此类别无法在编译期就决定要调用哪一个函数,需要在运行时才动态决定要调用哪一个函数。

Remove ads

实现

对象的虚拟方法表会包括对象动态绑定方法的存储器地址。会透过对象的虚拟方法表,从其中方法的地址来调用方法。属于同一个类别的对象会有相同的虚拟方法表,因此这些对象可以共享虚拟方法表。属于兼容类别的对象(例如继承自同一个类别的各类别下的对象)会有相同布置的虚拟方法表:在所有兼容类别内,特定方法会在虚拟方法表中相同的位置。因此透过虚拟方法表读取方法位置,就可以找到此对象方法的位置,以此调用函数[2]

C++标准没有强制指定动态分配实现的作法,不过各编译器都是依照相同的基本模式,只有小部分的差异。

一般来说,编译器会为每一个有虚拟方法的类别分别创建虚拟方法表。当产生一个对象时,这个对象会多一个隐藏成员,此成员是指向虚拟方法表的指针,也称为虚拟方法表指针vpointerVPTR。因此,编译器也需要在对象的构造器中增加隐藏代码,让新对象的虚拟方法表指针指向其虚拟方法表。

许多编译器会将虚拟方法表当作对象里的最后一名成员,也有编译器将虚拟方法表当作第一个成员。这两种方式都可以产生可移殖的代码[3]g++以往就将指针当成对象的最后一名成员[4]

Remove ads

相关条目

参考资料

Loading related searches...

Wikiwand - on

Seamless Wikipedia browsing. On steroids.

Remove ads