热门问题
时间线
聊天
视角

虚拟方法表

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

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