2011-07-07 24 views
8

Por lo que sé de CPP, cada clase tiene su propia vtable.mesa virtual/mesa de despacho

Sin embargo this enlace wikipedia menciones:

tabla de despacho de un objeto se contener las direcciones de métodos dinámicamente con destino del objeto. Método llamadas se realizan por ir a buscar la dirección del método de la mesa de despacho del objeto. La tabla de despacho es la misma para todos los objetos que pertenecen a la misma clase , y por lo tanto es normalmente compartido entre ellos.

Por favor alguien puede arrojar algo de luz.

Gracias!

+0

Nota: no todas las clases en C++ tienen tablas virtuales. Solo los que tienen funciones virtuales tienen. Cuando no hay funciones virtuales, todos los métodos pueden vincularse estáticamente (en tiempo de compilación) y el mecanismo de envío no es necesario en tiempo de ejecución. – eran

Respuesta

3

Sí, métodos virtuales son tratados de manera diferente por el compilador y el tiempo de ejecución.

Java: Todos los métodos en java son virtuales por defecto. Eso significa que cualquier método puede ser anulado cuando se usa en herencia, a menos que ese método se declare como final o estático.

Desde el VM Specification,

La máquina virtual Java no mandato de cualquier particular, estructura interna de los objetos. La marca de libro hay Unidos: En algunas de implementaciones de la máquina virtual de Java de Sun, una referencia a una instancia de clase es un puntero a un mango que es en sí mismo un par de punteros: uno a una mesa que contiene los métodos del objeto y un puntero al objeto Clase que representa el tipo del objeto , y el otro a la memoria asignada del montón para los datos del objeto .


C++:

Siempre que una función miembro de la clase se declara como virtual, el compilador crea una tabla virtual en la memoria que contiene todos los punteros de función que se declaran como virtual en esa clase . Esto permite el polimorfismo de tiempo de ejecución (es decir, averiguar la función deseada en tiempo de ejecución). Las tablas de funciones virtuales también tienen un puntero adicional en el objeto para el vtable. A medida que este puntero adicional y el vtable aumentan el tamaño del objeto, un diseñador de clases debe ser prudente al declarar funciones virtuales.

La secuencia de eventos al llamar a un método en el puntero del objeto base es:

  • Obtener puntero vtable (vtable este puntero apunta al comienzo de la viable).
  • Obtener los punteros de función en la viable uso de desplazamiento.

Invoca la función indirectamente a través del puntero vtable.

0

Esa cita indica que cada objeto tiene una tabla de envío, que se puede compartir entre la clase ya que son iguales para todas las instancias de la misma clase. ES DECIR. Cada clase tiene su propio vtable.

+0

thnx .. te refieres al revés .. cada clase tiene una tabla de distribución que es compartida por sus instancias [objetos] – codeObserver

1

Cada clase que tiene funciones virtuales (es decir, en Java es simplemente "todas las clases") tiene su propia vtable. Cada objeto ha ocultado una referencia a su clase vtable. Entonces, los objetos de la misma clase tienen referencias idénticas.

Al realizar la llamada del compilador método virtual por lo general hace una búsqueda:

obj.method(args); 

se traduce en algo

obj.vtable[idx_method](obj, args); 

A veces, si el compilador puede deducir el tipo particular de objeto, se puede emitir estática llamar en lugar de virtual. Por lo tanto, el código

MyObject obj(ctor_args); 
.... 
obj.method(args); 

se puede traducir en

MyObject_method(obj, args); 

Que por lo general se ejecutará más rápido que la llamada virtual.

9

A veces es más fácil de entender con un ejemplo:

class PureVirtual { 
    public: 
     virtual void methodA() = 0; 
     virtual void methodB() = 0; 
}; 

class Base : public PureVirtual { 
    public: 
     virtual void methodA(); 
     void methodC(); 
    private: 
     int x; 
}; 

class Derived : public Base { 
    public: 
     virtual void methodB(); 
    private: 
     int y; 
}; 

Así, dado un objeto de tipo derivado puede ser que parezca:

      ------------ 
Known offset for vtable | 0xblah | -------> [Vtable for type "Derived"] 
         ------------ 
Known offset for x  | 3  | 
         ------------ 
Known offset for y  | 2  | 
         ------------ 

Con la viable para el tipo "Derivado" buscando algo como:

      ------------ 
Known offset for "methodA" | 0xblah1 | ------> methodA from Base 
          ------------- 
Known offset for "methodB" | 0xblah2 | ------> methodB from Derived 
          ------------- 

Tenga en cuenta que ya que "methodC" no era virtual, no está en el vtable en absoluto. También tenga en cuenta que todas las instancias de la clase derivada tendrán un puntero vtable al mismo objeto vtable compartido (ya que tienen el mismo tipo).

Aunque las implementaciones para C++ y Java son ligeramente diferentes, las ideas no son incompatibles. La diferencia clave, desde un punto de vista conceptual, es que los métodos de Java son "virtuales" a menos que se declare "final". En C++, la palabra clave "virtual" debe darse explícitamente para que la función esté en el vtable. Todo lo que no esté en vtable se enviará utilizando los tipos de tiempo de compilación en lugar del tipo de tiempo de ejecución del objeto.