ProgrammingC++ Developer

Explain the difference between the keywords 'explicit' and 'implicit' when declaring constructors, and how their use affects object initialization in C++.

Pass interviews with Hintsage AI assistant

Answer

In C++, if a constructor can be called with a single argument, it is considered implicit by default. Such a constructor can be used for implicit type conversion. To protect against this, the keyword explicit is used.

  • explicit constructors prevent implicit conversions.

Using explicit allows you to avoid unexpected conversions that can occur, for example, when passing a mismatched type argument to functions or when initializing a variable.

Example:

struct Foo { explicit Foo(int x) { /* ... */ } }; Foo a = 10; // Error, explicit prevents implicit initialization Foo b(10); // Ok

If explicit weren't present, then the statement Foo a = 10; would be allowed and could lead to unexpected bugs.

Trick Question

Question: Do all constructors declared with explicit prevent being called during initialization with = ?
Common Answer: Yes, explicit prohibits any initialization with =.
Correct Answer: explicit only prevents implicit conversions. With direct initialization (ClassName obj(param);) the explicit constructor is called. With copy initialization (ClassName obj = param;) — no.

Example:

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

Examples of real errors due to misunderstanding of this topic


Story: A project had a constructor written without explicit, allowing initialization through types, which led to unexpected automatic conversions of function arguments. This caused hidden errors and made debugging difficult.



Story: A developer did not set explicit for the container constructor, and the default constructor suddenly began to be called during assignment or when passing other types. The result — incorrect logic for object creation and unpredictable behavior.



Story: An inexperienced programmer declared an explicit constructor but was surprised that direct initialization with parentheses worked, thinking that explicit blocks it as well. This led to the non-use of convenient safe patterns and unnecessary code in the project.