establecer el puntero vtable en consecuencia
Esta parte está casi completamente definida por la implementación. Su compilador puede no usar tablas virtuales. Puede haber múltiples punteros vtable, o uno o más punteros a cosas que no son tablas. La herencia múltiple siempre es entretenida, al igual que las clases base virtuales. No se garantiza que estos metadatos puedan copiarse con memcpy
a otro objeto, por lo que el/los puntero (s) no necesitan ser absolutos. Podría haber compensaciones allí que son relativas al puntero del objeto en sí.
IIRC lo que comúnmente ocurre es que se llama al constructor de la clase base, luego el puntero vtable se establece a la clase base, luego se llama al primer constructor de clase derivado, etc. Esto es para satisfacer los requisitos de la especificación sobre lo que ocurre cuando se llama a una función virtual en un constructor. Por lo que recuerdo, no hay una "lista de acciones" en el estándar, solo un orden de inicialización definido.
Así que no es posible generalizar lo que hace una implementación, especialmente porque lo que tienes no es una implementación del estándar C++. Si corta las esquinas al omitir "nuevo", presumiblemente con una buena razón porque cree que no deberías estar usándolo en la plataforma objetivo, entonces quién sabe qué otras reglas del idioma ignora. Si fuera posible simular "nuevo" con un malloc y un poco de empuje de puntero, ¿por qué el compilador no solo implementa el nuevo? Creo que debes hacer preguntas etiquetadas con tu compilador y plataforma específicos, para que cualquier experto en tu compilador pueda responder.
+1 para entender la construcción de la clase base virtual –