2011-07-06 7 views

Respuesta

14

La maquinaria para llamadas virtuales (normalmente una tabla v, pero no necesita estar) se configura durante ctor-initializer, después de la construcción de subobjetos base y antes de la construcción de miembros. Sección [class.base.init] decretos:

Las funciones de miembro (incluidas las funciones miembro virtual, 10.3) se pueden llamar para un objeto en construcción. Del mismo modo, un objeto en construcción puede ser el operando del operador typeid (5.2.8) o de un dynamic_cast (5.2.7). Sin embargo, si estas operaciones se realizan en un ctor-inicializador (o en una función llamada directa o indirectamente de un ctor-inicializador) antes de todos los MEM-inicializadores para clases de base han completado, el resultado de la operación es indefinido.

En realidad, durante la construcción de los subobjetos base, existe la maquinaria de función virtual, pero está configurada para la clase base. Sección [class.cdtor] dice:

Las funciones miembro, incluyendo las funciones virtuales (10.3), se puede llamar durante la construcción o destrucción (12.6.2). Cuando una función virtual es llamada directa o indirectamente desde un constructor o desde un destructor, incluso durante la construcción o destrucción de los miembros de datos no estáticos de la clase, y el objeto al que se aplica la llamada es el objeto (llámelo x) en construcción o destrucción, la función llamada es la desbordamiento final en la clase del constructor o del destructor y no una sobrescritura en una clase más derivada. Si la llamada a función virtual usa un acceso de miembro de clase explícito (5.2.5) y la expresión de objeto hace referencia al objeto completo de x o uno de los subobjetos de clase base de ese objeto pero no a x o uno de sus subobjetos de clase base, el comportamiento no está definido .

+0

Doe s esto significa que el 'vptr' se modificará cada vez que se construyan los subobjetos base, si hay muchos niveles de derivación? – fengqi

2

se inicializa entre los constructores de la base y las clases derivadas:

class Base { Base() { } virtual void f(); }; 
class Derived { Derived(); virtual void f(); }; 

Esto ocurre cuando la memoria en bruto se convierte en objeto base. Ocurre cuando el objeto Base se convierte en Objeto derivado durante la construcción de un objeto. Lo mismo sucede obviamente en reversa cuando se destruye un objeto. Es decir. cada vez que cambia el tipo, se cambia el puntero vtable . (Estoy seguro de que alguien comenta que los vtables no necesitan existir de acuerdo con la norma ...)

0

This msdn article explains it in great detali

Allí se dice:

"Y la respuesta final es ... como era de esperar Sucede en el constructor.".

so ..
A :: A(): i (0), j (0)
{
- >> aquí!
// ... //

}

Pero tenga cuidado, digamos que usted tiene la clase A, y una clase A1 deriva de A.

  • Si crea un nuevo Una objeto, el VPTR se encuentra justo al comienzo del constructor de la clase a
  • Pero si tuviera que crear un nuevo objeto A1:

"Aquí está toda la secuencia de eventos cuando cree una instancia de la clase A1:

  1. A1 :: A1 llama a un :: Un
  2. A :: A conjuntos VTABLE al de un vtable
  3. A: : a ejecuta y devuelve
  4. A1 :: A1 establece vtable a vtable
  5. ejecuta y devuelve
  6. A1 :: A1 de A1 "
+1

La primera cita estándar que di en mi respuesta muestra que su explicación no es del todo correcta. Cuando agrega una respuesta tardía, es bueno leer y comprender las respuestas existentes, por las dudas. –

Cuestiones relacionadas