Taula de mètodes virtual
A la programació d'ordinadors, una taula de mètodes virtuals (VMT), una taula de funcions virtuals, una taula de trucades virtuals, una taula de distribució, vtable o vftable és un mecanisme utilitzat en un llenguatge de programació per donar suport a l'enviament dinàmic (o enllaç de mètodes en temps d'execució).[1]
Sempre que una classe defineix una funció virtual (o mètode), la majoria dels compiladors afegeixen una variable de membre oculta a la classe que apunta a una matriu de punters a funcions (virtuals) anomenada taula de mètodes virtuals. Aquests punters s'utilitzen en temps d'execució per invocar les implementacions de funcions adequades, perquè en temps de compilació encara no es pot saber si la funció base s'ha de cridar o una de derivada implementada per una classe que hereta de la classe base.[2]
Hi ha moltes maneres diferents d'implementar aquest enviament dinàmic, però l'ús de taules de mètodes virtuals és especialment comú entre C++ i llenguatges relacionats (com D i C#). Els llenguatges que separen la interfície programàtica dels objectes de la implementació, com Visual Basic i Delphi, també solen utilitzar aquest enfocament, perquè permet als objectes utilitzar una implementació diferent simplement utilitzant un conjunt diferent de punters de mètode. El mètode permet la creació de biblioteques externes, on altres tècniques potser no.[3]
Suposem que un programa conté tres classes en una jerarquia d'herència: una superclasse ,Cat, i dues subclasses ,HouseCat iLion. ClasseCat defineix una funció virtual anomenadaspeak, de manera que les seves subclasses poden proporcionar una implementació adequada (pmeow oroar). Quan el programa crida alspeakfunció en aCatReferència (que pot referir-se a una instància deCat, o una instància deHouseCat oLion ), el codi ha de poder determinar a quina implementació de la funció s'ha d' enviar la trucada. Això depèn de la classe real de l'objecte, no de la classe de la referència a aquest (Cat). En general, la classe no es pot determinar estàticament (és a dir, en temps de compilació), de manera que el compilador tampoc pot decidir quina funció cridar en aquest moment. La trucada s'ha d'enviar a la funció correcta de forma dinàmica (és a dir, en temps d'execució).[4]
Implementació
modificaLa taula de mètodes virtuals d'un objecte contindrà les adreces dels mètodes enllaçats dinàmicament de l'objecte. Les trucades de mètodes es realitzen obtenint l'adreça del mètode de la taula de mètodes virtuals de l'objecte. La taula de mètodes virtual és la mateixa per a tots els objectes que pertanyen a la mateixa classe i, per tant, normalment es comparteixen entre ells. Els objectes que pertanyen a classes compatibles amb tipus (per exemple, germans en una jerarquia d'herència) tindran taules de mètodes virtuals amb la mateixa disposició: l'adreça d'un mètode determinat apareixerà amb el mateix desplaçament per a totes les classes compatibles amb els tipus. Així, obtenir l'adreça del mètode d'un desplaçament donat a una taula de mètodes virtual obtindrà el mètode corresponent a la classe real de l'objecte.
Exemple
modificaConsidereu les declaracions de classe següents en la sintaxi C++:
class B1 {
public:
virtual ~B1() {}
void fnonvirtual() {}
virtual void f1() {}
int int_in_b1;
};
class B2 {
public:
virtual ~B2() {}
virtual void f2() {}
int int_in_b2;
};
s'utilitza per derivar la classe següent:
class D : public B1, public B2 {
public:
void d() {}
void f2() override {}
int int_in_d;
};
i el següent fragment de codi C++:
B2 *b2 = new B2();
D *d = new D();
g++ 3.4.6 de GCC produeix el següent disseny de memòria de 32 bits per a l'objecte b2
:
b2: +0: pointer to virtual method table of B2 +4: value of int_in_b2 virtual method table of B2: +0: B2::f2()
i el següent disseny de memòria per a l'objecte d
:
d:
+0: pointer to virtual method table of D (for B1) +4: value of int_in_b1 +8: pointer to virtual method table of D (for B2) +12: value of int_in_b2 +16: value of int_in_dTotal size: 20 Bytes.
virtual method table of D (for B1):
+0: B1::f1() // B1::f1() is not overriddenvirtual method table of D (for B2):
+0: D::f2() // B2::f2() is overridden by D::f2() // The location of B2::f2 is not in the virtual method table for D
Tingueu en compte que aquelles funcions que no porten la paraula clau virtual
a la seva declaració (com ara fnonvirtual()
i d()
) no apareixen generalment a la taula de mètodes virtuals. Hi ha excepcions per a casos especials que planteja el constructor predeterminat.
Referències
modifica- ↑ «25.6 — The virtual table – Learn C++» (en anglès). [Consulta: 29 novembre 2023].
- ↑ Misiak, Tim. «What's a vtable? What's an IUnknown?» (en anglès americà), 18-12-2022. [Consulta: 29 novembre 2023].
- ↑ Zendra, Olivier. 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 (en anglès). Centre de Recherche en Informatique de Nancy Campus Scientifique, Bâtiment LORIA, 1997, p. 16.
- ↑ «virtual function specifier - cppreference.com» (en anglès). [Consulta: 29 novembre 2023].