Es una opción de diseño del lenguaje.
Un constructor es una operación de una vez (por objeto) que crea un nuevo objeto en la memoria no inicializada. Solo se puede llamar a un constructor para un objeto, una vez que ha finalizado, comienza la vida del objeto y no se puede llamar ni reanudar ningún otro constructor en ese objeto.
En el otro extremo de su vida, un destructor solo puede (válidamente) llamarse una vez por objeto y tan pronto como se ingresa el destructor, la vida útil del objeto termina.
Una razón prinicipal para esto es hacer explícita cuando se llevará a cabo un destructor de objetos y en qué estado se puede esperar que el objeto de estar en.
Si un constructor de la clase completa satisfactoriamente entonces se le puede llamar destructor, de lo contrario la vida del objeto nunca ha comenzado y no se llamará al destructor. Esta garantía puede ser importante cuando un objeto adquiere recursos en su constructor que necesitan ser liberados en su destructor. Si la adquisición del recurso falla, generalmente se hará que el constructor falle; si el destructor se ejecutó de todos modos, podría intentar liberar un recurso que nunca se había adquirido con éxito.
Si permite que los constructores se llamen entre sí, puede no quedar claro si una llamada o un constructor llamado es responsable del recurso. Por ejemplo, si el constructor que realiza la llamada falla después de que el constructor llamado retorna, ¿debería ejecutarse el destructor? El constructor llamado puede haber adquirido algo que necesita ser liberado o tal vez eso fue lo que causó que fallara el construtor llamante y no se debe llamar al destructor porque el identificador del recurso nunca fue válido.
Para simplificar las reglas de destrucción, es más simple si cada objeto es creado por un único constructor y, si se crea correctamente, destruido por un solo destructor.
Tenga en cuenta que en C++ 11 un constructor podrá delegar en un constructor diferente, pero existen limitaciones que realmente no relajan el principal de una construcción por objeto. (El constructor principal puede reenviar a un constructor de destino, pero si lo hace no debe nombrar a nada más (clases base o miembros) en su lista de inicializadores.Estos serán inicializados por el constructor de destino, una vez que el constructor de destino devuelve el cuerpo del constructor principal se completará (inicialización adicional). No es posible reconstruir ninguna base o miembros, aunque le permite compartir código de constructor entre constructores.)
Este es el método preferido –
Se puede preferir pero es ineficaz ya que todos los miembros se construyen primero por defecto, luego se sobrescriben mediante la inicialización. –
Bueno, eso se convierte en una cuestión de optimización frente a minimizar la duplicación de código. Depende de qué es más importante para el programador que escribe. –