ProgrammatieC++/Backend Ontwikkelaar

Wat zijn delegatieconstructors in C++, wanneer en waarom zou je ze gebruiken?

Slaag voor sollicitatiegesprekken met de Hintsage AI-assistent

Antwoord.

Geschiedenis van de vraag

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.

Probleem

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.

Oplossing

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:

  • Voorkomt duplicatie van initialisatiecode
  • Verhoogt betrouwbaarheid en onderhoudbaarheid
  • Delegatie binnen de initialisatie-lijst, niet binnen de constructor-body

Vragen met een valstrik.

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) {} };

Typische fouten en anti-patterns

  • Vermindering van leesbaarheid door een overabundance aan delegatieconstructors
  • Circulaire delegatie — compilatiefout
  • Pogingen om een oproep naar de basisklasse constructor te delegeren via een delegatieconstructor

Voorbeeld uit het leven

Negatief geval

Drie constructors, elk initialiseert expliciet de velden, logica is niet gesynchroniseerd — wijziging wordt alleen aangebracht in één constructor, de andere twee zijn onjuist.

Voordelen:

  • Eenvoudig te schrijven

Nadelen:

  • Hoog risico op logica-afwijking tussen constructors

Positief geval

Eén hoofdconstructor, de andere delegeren naar hem, alle initialisatie-logica is gecentraliseerd.

Voordelen:

  • Gemakkelijk onderhoud, afwijkingen in logica zijn uitgesloten
  • Minimalisatie van code-duplicatie

Nadelen:

  • Je moet wennen aan de initialisatie-lijst-syntax