Antes del estándar C++11, al necesitar escribir varios constructores con diferentes parámetros, era necesario duplicar el código de inicialización en cada uno de ellos, ya que no había forma de llamar a otro constructor dentro de los constructores de la clase.
La imposibilidad de usar la lógica de inicialización ya existente en otros constructores llevaba a la duplicación de código y a errores al cambiar la lógica de inicialización: al actualizar un constructor, era fácil olvidar los demás.
Con la llegada de C++11, apareció el mecanismo de "constructores delegantes", que permite a un constructor de clase llamar a otro constructor de la misma clase a través de la sintaxis de lista de inicialización.
Ejemplo de código:
class Widget { public: Widget() : Widget(0, "predeterminado") {} Widget(int n) : Widget(n, "usuario") {} Widget(int n, std::string name) : size(n), label(name) {} private: int size; std::string label; };
Ahora toda la lógica común está centralizada en un "constructor principal", el resto delega la llamada.
Características clave:
¿Se puede delegar la llamada a otro constructor mediante la llamada a una función dentro del cuerpo del constructor?
No. La llamada a un constructor desde otro constructor solo es posible a través de la lista de inicialización, no dentro del cuerpo del constructor. Si se llama a una función desde el cuerpo del constructor, los miembros del objeto ya estarán inicializados.
¿Qué pasará si se crea un "ciclo" de delegación entre constructores?
La delegación cíclica (por ejemplo, A delega a B, y B a A) resulta en un error de compilación en C++: no puede haber recursión infinita entre constructores.
¿Se puede delegar la llamada a un constructor de clase base mediante un constructor delegante de una clase derivada?
No. Los constructores delegantes solo funcionan dentro de una sola clase. Para llamar al constructor base se utiliza una sintaxis separada:
class Base { public: Base(int) {} }; class Derived : public Base { public: Derived() : Base(42) {} };
Tres constructores, cada uno inicializa explícitamente los campos, la lógica no está sincronizada - se modifica solo uno, los otros dos son incorrectos.
Pros:
Contras:
Un constructor principal, el resto le delegan, toda la lógica de inicialización está centralizada.
Pros:
Contras: