Tot de C++11-standaard was het noodzakelijk om meerdere constructors met verschillende parameters te schrijven, wat leidde tot duplicatie van initialisatiecode in elk van hen, omdat er geen mogelijkheid was om een andere constructor binnen de class constructors aan te roepen.
De onmogelijkheid om bestaande initialisatie-logica in andere constructors te gebruiken leidde tot code-dubbelingen en fouten bij het wijzigen van de initialisatie-logica: wanneer je één constructor bijwerkt, vergeet je gemakkelijk de anderen.
Met de komst van C++11 werd het mechanisme van "delegatieconstructors" geïntroduceerd, waarmee de ene constructor van de class een andere constructor van dezelfde class kan aanroepen via de initialisatie-lijst-syntax.
Voorbeeld van code:
class Widget { public: Widget() : Widget(0, "default") {} Widget(int n) : Widget(n, "user") {} Widget(int n, std::string name) : size(n), label(name) {} private: int size; std::string label; };
Nu is alle gemeenschappelijke logica gecentraliseerd in één "hoofd" constructor, terwijl alle andere aanroepen delegeren.
Belangrijke kenmerken:
Kan je een oproep naar een andere constructor delegeren via het aanroepen van een functie binnen de body van de constructor?
Nee. Het aanroepen van een constructor vanuit een andere constructor is alleen mogelijk via de initialisatie-lijst, niet binnen de body van de constructor. Als je een functie vanuit de body van de constructor aanroept, zijn de objectleden al geïnitialiseerd.
Wat gebeurt er als je een "ring" van delegatie tussen constructors maakt?
Circulaire delegatie (bijvoorbeeld A delegeert naar B, en B delegeert naar A) leidt tot een compilatiefout in C++: oneindige recursie tussen constructors is niet mogelijk.
Kan je een oproep naar de constructor van de basisklasse delegeren met een delegatieconstructor van de afgeleide klasse?
Nee. Delegatieconstructors werken alleen binnen dezelfde class. Voor het aanroepen van de basisklasse constructor wordt een aparte syntax gebruikt:
class Base { public: Base(int) {} }; class Derived : public Base { public: Derived() : Base(42) {} };
Drie constructors, elk initialiseert expliciet de velden, logica is niet gesynchroniseerd — wijziging wordt alleen aangebracht in één constructor, de andere twee zijn onjuist.
Voordelen:
Nadelen:
Eén hoofdconstructor, de andere delegeren naar hem, alle initialisatie-logica is gecentraliseerd.
Voordelen:
Nadelen: