ProgrammazioneSviluppatore C++

Spiega la differenza tra le parole chiave 'explicit' e 'implicit' nella dichiarazione dei costruttori e come il loro utilizzo influisce sull'inizializzazione degli oggetti in C++.

Supera i colloqui con l'assistente IA Hintsage

Risposta

In C++, se un costruttore può essere chiamato con un solo argomento, per impostazione predefinita è considerato implicit. Un costruttore di questo tipo può essere utilizzato per conversioni di tipo implicite. Per proteggersi da questo, si utilizza la parola chiave explicit.

  • I costruttori explicit vietano le conversioni implicite.

L'uso di explicit consente di evitare conversioni inaspettate che possono verificarsi, ad esempio, quando si passa un argomento di tipo non corrispondente a una funzione o durante l'inizializzazione di una variabile.

Esempio:

struct Foo { explicit Foo(int x) { /* ... */ } }; Foo a = 10; // Errore, explicit vieta l'inizializzazione implicita Foo b(10); // Ok

Se non ci fosse stato explicit, la scrittura Foo a = 10; sarebbe stata consentita e potrebbe aver portato a bug inaspettati.

Domanda insidiosa

Domanda: Tutti i costruttori dichiarati con explicit non possono essere chiamati durante l'inizializzazione con = ?
Risposta comune: Sì, explicit vieta qualsiasi inizializzazione con =.
Risposta corretta: explicit vieta solo le conversioni implicite. Con l'inizializzazione diretta (ClassName obj(param);) il costruttore explicit viene chiamato. Con l'inizializzazione per copia (ClassName obj = param;) – no.

Esempio:

struct A { explicit A(int) {} }; A x = 1; // Errore A y(1); // OK

Esempi di errori reali a causa della mancanza di conoscenza delle sfumature dell'argomento


Storia: In un progetto è stato scritto un costruttore senza explicit, consentendo l'inizializzazione tramite tipi, il che ha portato a conversioni automatiche inaspettate degli argomenti delle funzioni. Questo ha causato errori nascosti e ha reso difficile il debug.



Storia: Un sviluppatore non ha messo explicit per il costruttore di un contenitore e il costruttore predefinito ha iniziato ad essere chiamato inaspettatamente durante l'assegnazione o la trasmissione di altri tipi. Risultato — logica di creazione degli oggetti non corretta e comportamento imprevedibile.



Storia: Un programmatore inesperto ha dichiarato un costruttore explicit, ma è rimasto sorpreso che l'inizializzazione diretta con le parentesi tonde funziona, pensando che explicit lo bloccasse. Questo ha portato a non utilizzare schemi sicuri e utili e a codice superfluo nel progetto.