📑 Table of Contents

程序设计中的虛擬方法表(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 [2025-02-03]. (原始内容存档于2021-12-07). 
  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). 

📚 Artikel Terkait di Wikipedia

钩子编程

VirtualTable { // example class public: virtual void VirtualFunction01( ticket ); }; void VirtualTable::VirtualFunction01( ticket ) { printf("VirtualFunction01

ASP.NET MVC Framework

GetList() { return View(BlogDataModel); } Function GetList() As ActionResult Return View(BlogDataModel) End Function 在 ASP.NET MVC 中,Model

可移植可执行

Export Table: .edata Section Import Table: .idata Section. Resource Table: .rsrc Section. Exception Table: .pdata Section. Certificate Table: 指向Attribute

标准模板库

virtual)函數的執行效率,這便違反的前面所說的「效率」原則。 到了C++模板觀念,Stepanov參加了許多有關的研討會,與C++之父比雅尼討論模板的设计細節。如,Stepanov認為C++的函數模板(function

模板元編程

return 0; } 喚起的 virtual 函式是屬於位於繼承最下位之類別的。這種動態多型(dynamically polymorphic)行為是藉由擁有虛擬函式的類別所產生的虛擬函式表(virtual look-up tables(英语:Virtual method table

指標 (電腦科學)

統呼叫流程,以及動態連結資料庫(DLL)的進入點位址。在物件導向程式設計中,使用函數指標(Function pointer)來綁定方法(method),常見於虛擬方法表(Virtual method table)中。 但是指標本身也存在一些可被濫用之处,在存取某個資料結構時,可能會超出可用範圍,使軟

Simula

例如,下面实现散列表的HashTable类,声明了整数类型的虚过程hash并随即实现了它,又定义了要用到这个散列函数hash的查找过程lookup: class HashTable(n); integer n; virtual: integer procedure hash; begin

Python

  venv — Creation of virtual environments. [2023-05-07]. (原始内容存档于2023-06-13).  virtualenv — A tool for creating isolated virtual python environments.