2010-10-03 10 views

Respuesta

11

A vtable no es un concepto de C++ por lo que si se usan y cuándo se crean, si se usan dependerán de la implementación.

Normalmente, vtables son estructuras creadas en tiempo de compilación (porque pueden determinarse en tiempo de compilación). Cuando se crean objetos de un tipo particular en tiempo de ejecución, tendrán un vptr que se inicializará para apuntar a vtable estática en tiempo de construcción.

+0

Gracias, pero uno de mis instructores me dijo que se crea un vtable antes de llamar a la función principal. Se crea durante el código StartupCRT. Solo quería confirmar eso y entender más sobre eso. – Sen

+4

@Sen: Tal vez, pero quizás no. Una implementación de C++ no tiene que usar _vtables_ por lo tanto, si incrustado en el binario, construido en el código de inicio o asignado dinámicamente cuando sea necesario (poco probable) depende totalmente de la implementación. Lo que la implementación decida hacer debe ser transparente para el programa, por lo que debería ser mucho más importante que el programador sepa qué comportamiento esperar del uso de las funciones virtuales que cómo se implementan en la plataforma particular que está utilizando. –

+1

@Sen: StartupCRT suena muy parecido a algo específico de Microsoft, y lo que le dijo puede ser cierto para Visual C++ de Microsoft, pero como dice Charles, el Estándar C++ en sí mismo permite que cada proveedor de compiladores elija la implementación que quiera durante tanto tiempo. ya que funciona correctamente. Otros proveedores probablemente ni siquiera tendrán una función "StartupCRT". – user433534

3

El vtable se crea en tiempo de compilación. Cuando se crea un objeto nuevo durante el tiempo de ejecución, el puntero vtable oculto se establece para que apunte a la variable vtable.

Tenga en cuenta, sin embargo, que no puede hacer un uso confiable si las funciones virtuales hasta que el objeto está completamente construido. (No hay funciones virtuales de llamada en el constructor.)

EDIT Pensé en responder a las preguntas en los comentarios.

Como se ha señalado, los detalles exactos de cómo se crea y usa el vtable se dejan a la implementación. La especificación C++ solo proporciona comportamientos específicos que deben ser garantizados, por lo que hay mucho margen de maniobra para la implementación. No tiene que usar tablas virtuales (aunque la mayoría lo hace). En general, no necesita saber esos detalles. Solo necesita saber que cuando llama a una función virtual, hace lo que espera independientemente de cómo lo hace.

Dicho esto, aclararé un par de puntos acerca de una implementación típica. Una clase con funciones virtuales tiene un puntero oculto (lo llamaremos vptr) que apunta al vtable para esa clase. Supongamos que tenemos una clase de empleado:

class Employee { 
public: 
    virtual work(); 
}; 

Esta clase tendrá un VPTR en su estructura, lo que en realidad puede tener este aspecto:

class Employee { 
public: 
    vtble *vptr; // hidden pointer 
    virtual work(); 
}; 

Cuando derivamos de esta clase, sino que también tendrá un vptr, y debe estar en el mismo lugar (en este caso, al principio). De esta forma, cuando se llama a una función, independientemente del tipo de clase derivada, siempre utiliza el vptr al principio para encontrar el vtable correcto.

+3

Estrictamente, el uso de funciones virtuales en un constructor es confiable. El resultado está bien definido (que no sea para funciones virtuales puras), pero generalmente no es lo que se desea. –

+0

Hola JoshD, ¿podrías explicar la siguiente línea que dijiste: "Cuando se crea un objeto nuevo durante el tiempo de ejecución, el puntero vtable oculto se establece para que apunte al vtable". Como soy principiante, me resulta difícil de entender. – Sen

+1

Charles tiene razón, pero prácticamente no es malo tener una expectativa general de lo que realmente hacen los compiladores, siempre y cuando no confíe demasiado en ella, y su descripción sea realista. @Sen: si dices 'Employee e', donde Employee es una clase con métodos virtuales, entonces el nuevo objeto e generalmente tiene espacio reservado por el compilador para un puntero al vtable para Employee. Si tuviera un Presidente derivado del Empleado, su puntero vtable apuntaría al Presidente vtable, pero ambos punteros vtable estarán en la misma compensación en relación con otros miembros de datos del Empleado. – user433534

Cuestiones relacionadas