La jerarquía de las llamadas a los constructores plantea un interesante dilema. ¿Qué ocurre si se está dentro de un constructor y se llama a una función virtual? Dentro de una función miembro ordinaria se puede imaginar qué ocurrirá - la llamada virtual es resuelta en tiempo de ejecución porque el objeto no puede saber si pertenece a la clase en la que está la función miembro o a alguna clase derivada de ella. Por coherencia, se podría pensar que también es lo que debería ocurrir dentro de los constructores.
No es el caso. Si se llama a una función virtual dentro de un constructor, sólo se usa la versión local de la función. Es decir, el mecanismo virtual no funciona dentro del constructor.
Este comportamiento tiene sentido por dos motivos. Conceptualmente, el trabajo del constructor es dar al objeto una existencia (lo cual no es precisamente una hazaña corriente). Dentro de cualquier constructor, el objeto puede estar formado sólo parcialmente - se puede saber sólo que los objetos de la clase base han sido inicializados, pero no se puede saber qué clases heredan de ésta. Una llamada a una función virtual, sin embargo, llega «hacia delante» o «hacia fuera» dentro de la jerarquía de herencia. Llama a una función de una clase derivada. Si se pudiera hacer esto dentro de un constructor, se estaría llamando a una función que podría manipular miembros que todavía no han sido inicializados, una receta segura para el desastre.
El segundo motivo es mecánico. Cuando se llama a un constructor, una de las primeras cosas que hace es inicializar su VPTR. Sin embargo, sólo puede saber que es del tipo «actual» - el tipo para el que se ha escrito el constructor. El código del constructor ignora completamente si el objeto está en la base de otra clase. Cuando el compilador genera código para ese constructor, se genera código para un constructor de esa clase, no para la clase base, ni para una clase derivada (debido a que una clase no puede saber quién la hereda). Por eso, el VPTR que use debe apuntar a la VTABLE de esa clase. El VPTR permanece inicializado a esa VTABLE durante el resto de la vida del objeto, a menos que ésta no sea la última llamada a un constructor. Si posteriormente se llama a un constructor de una clase más derivada, ese constructor pone el VPTR a su VTABLE, y así hasta que el último constructor termine. El estado del VPTR es determinado por el constructor que sea llamado en último lugar. Ésta es otra razón por la que los constructores son llamados en orden desde la base al más derivado.
Pero mientras que toda esta serie de llamadas al constructor tiene lugar, cada constructor ha puesto el VPTR a su propia VTABLE. Si se usa el mecanismo virtual para llamar a funciones, producirá sólo una llamada a través de su propia VTABLE, y no de la VTABLE del más derivado (como debería suceder después de que todos los constructores hayan sido llamados). Además, muchos compiladores reconocen cuándo se hace una llamada a una función virtual dentro de un constructor, y realizan una ligadura estática porque saben que la ligadura dinámica sólo producirá una llamada a la función local. En cualquier caso, no se conseguirán los resultados que se podían esperar inicialmente de la llamada a una función virtual dentro de un constructor.