programowanieProgramista C++

Wyjaśnij różnicę między słowami kluczowymi 'explicit' i 'implicit' podczas deklarowania konstruktorów oraz jak ich zastosowanie wpływa na inicjalizację obiektów w C++.

Zdaj rozmowy kwalifikacyjne z asystentem AI Hintsage

Odpowiedź

W C++, jeśli konstruktor może być wywołany z jednym argumentem, jest domyślnie uważany za implicit (niejawny). Taki konstruktor może być używany do niejawnej konwersji typów. Aby się przed tym bronić, stosuje się słowo kluczowe explicit.

  • explicit konstruktorzy zabraniają niejawnych konwersji.

Użycie explicit pozwala uniknąć nieoczekiwanych konwersji, które mogą wystąpić, na przykład, przy przekazywaniu do funkcji argumentu innego typu lub przy inicjalizacji zmiennej.

Przykład:

struct Foo { explicit Foo(int x) { /* ... */ } }; Foo a = 10; // Błąd, explicit zabrania niejawnej inicjalizacji Foo b(10); // OK

Gdyby nie było explicit, zapis Foo a = 10; byłby dozwolony i mógłby prowadzić do nieoczekiwanych błędów.

Pytanie podchwytliwe

Pytanie: Czy wszystkie konstruktory zadeklarowane jako explicit nie mogą być wywoływane przy inicjalizacji z = ?
Częsta odpowiedź: Tak, explicit zabrania wszelkiej inicjalizacji z =.
Poprawna odpowiedź: explicit zabrania tylko niejawnych konwersji. Z inicjalizacją bezpośrednią (ClassName obj(param);) konstruktor explicit jest wywoływany. Przy inicjalizacji kopią (ClassName obj = param;) — nie.

Przykład:

struct A { explicit A(int) {} }; A x = 1; // Błąd A y(1); // OK

Przykłady rzeczywistych błędów z powodu nieznajomości niuansów tematu


Historia: W projekcie napisano konstruktor bez explicit, umożliwiający inicjalizację przez typy, co prowadziło do nieoczekiwanych automatycznych konwersji argumentów funkcji. Spowodowało to pojawienie się ukrytych błędów i utrudniło debugowanie.



Historia: Programista nie umieścił explicit dla konstruktora kontenera, a konstruktor domyślny nagle zaczął być wywoływany przy przypisaniu lub przekazywaniu innych typów. Efekt — niepoprawna logika tworzenia obiektów i nieprzewidywalne zachowanie.



Historia: Niedoświadczony programista zadeklarował explicit konstruktor, ale był zaskoczony, że inicjalizacja bezpośrednia z okrągłymi nawiasami działa, myśląc, że explicit blokuje i tę. Prowadziło to do nieużywania wygodnych bezpiecznych wzorców i zbędnego kodu w projekcie.