跳转到内容

虚拟方法表

本页使用了标题或全文手工转换
维基百科,自由的百科全书

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

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

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

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

实现

[编辑]

物件的虚拟方法表会包括物件动态绑定方法的记忆体位址。会透过物件的虚拟方法表,从其中方法的位址来呼叫方法。属于同一个类别的物件会有相同的虚拟方法表,因此这些物件可以共用虚拟方法表。属于相容类别的物件(例如继承自同一个类别的各类别下的物件)会有相同布置的虚拟方法表:在所有相容类别内,特定方法会在虚拟方法表中相同的位置。因此透过虚拟方法表读取方法位置,就可以找到此物件方法的位置,以此呼叫函式[2]

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

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

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

相关条目

[编辑]

参考资料

[编辑]
  • Margaret A. Ellis and Bjarne Stroustrup (1990) The Annotated C++ Reference Manual. Reading, MA: Addison-Wesley. (ISBN 0-201-51459-1)
  1. ^ Zendra, Olivier; Colnet, Dominique; Collin, Suzanne. Efficient Dynamic Dispatch without Virtual Function Tables: The SmallEiffel Compiler -- 12th Annual ACM SIGPLAN Conference on Object-Oriented Programming Systems, Languages and Applications (OOPSLA'97), ACM SIGPLAN, Oct 1997, Atlanta, United States. pp.125-141. inria-00565627. Centre de Recherche en Informatique de Nancy Campus Scientifique, Bâtiment LORIA. 1997: 16. 
  2. ^ Ellis & Stroustrup 1990, pp. 227–232
  3. ^ Danny Kalev. "C++ Reference Guide: The Object Model II". 2003. Heading "Inheritance and Polymorphism" and "Multiple Inheritance".
  4. ^ C++ ABI Closed Issues. [2011-06-17]. (原始内容存档于25 July 2011).  无效|url-status=bot: unknown (帮助)