The explicit Keyword in C++: Complete Breakdown with Code Examples

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

What Lies Behind the explicit Keyword in C++? A Complete Code Breakdown

\n\n

Have you ever written code in C++ and suddenly noticed that a function accepts one type, but you're passing a completely different one — and the compiler silently agrees? Or, even worse, a bug appears in the code that's impossible to catch by eye because everything looks logical? Meet: implicit type conversion — one of the most insidious features of C++ that can either simplify your life or turn it into a nightmare. And this is precisely where the explicit keyword enters the stage.

\n\n

In this article, we'll break down what explicit is, why it's needed, how to use it, and most importantly — how it saves you from errors that are hard to find. We'll go from simple to complex: start with a basic example and finish with real-world production scenarios. Let's go!

\n\n

The Problem: Implicit Constructors — Evil or Good?

\n\n

Imagine you have a simple class for working with fractions:

\n\n
class Fraction {\npublic:\n    int numerator;\n    int denominator;\n\n    // Constructor with one parameter\n    Fraction(int num) : numerator(num), denominator(1) {}\n};
\n\n

Everything looks harmless, right? Now let's write a function that takes a fraction:

\n\n
void printFraction(const Fraction& f) {\n    std::cout << f.numerator << "/" << f.denominator << std::endl;\n}
\n\n

And now — attention! — the most dangerous moment:

\n\n
printFraction(5); // ???\n
\n\n

The compiler will compile this without a single error. Why? Because it will implicitly call the constructor Fraction(int) and turn the number 5 into a Fraction(5/1) object. At first glance — convenient. But imagine you accidentally pass a number where an object was expected, and the program behaves strangely. Debugging such a bug can take hours.

\n\n

Here's an even more illustrative example — imagine a class for working with passwords:

\n\n
class Password {\npublic:\n    Password(const std::string& str) : value(str) {}\n    bool isValid() const { return value.length() >= 8; }\nprivate:\n    std::string value;\n};
\n\n

Now imagine a function:

\n\n
void checkPassword(const Password& p) {\n    if (p.isValid()) {\n        std::cout << "Password is strong" << std::endl;\n    } else {\n        std::cout << "Password is too short" << std::endl;\n    }\n}
\n\n

And the call:

\n\n
checkPassword("12345"); // OOPS!\n
\n\n

The compiler silently creates a Password object from the string "12345", and the function works. But why? Did we really want any string literal to automatically become a password? Hardly. This is exactly where explicit is needed.

\n\n

The Solution: The explicit Keyword

\n\n

The explicit keyword is placed before a constructor and forbids implicit conversions. Now, if someone tries to pass a number or string where an object of your class is expected, the compiler will produce an error. Let's rewrite our Fraction class:

\n\n
class Fraction {\npublic:\n    int numerator;\n    int denominator;\n\n    explicit Fraction(int num) : numerator(num), denominator(1) {}\n};
\n\n

Now this code will not compile:

\n\n
printFraction(5); // Compilation error!\n
\n\n

But you can still explicitly create an object:

\n\n
printFraction(Fraction(5)); // Works fine\nprintFraction(static_cast<Fraction>(5)); // Also works\n
\n\n

So explicit does not forbid creating an object — it forbids automatic, implicit creation. It's like a door with a sign saying "pass holders only": you can enter, but only if you show your ID.

\n\n

When to Use explicit? Practical Recommendations

\n\n

The golden rule is: always use explicit for single-argument constructors, unless you have a very good reason not to. This simple habit will save you from hundreds of hours of debugging. In modern C++ (starting from C++11), you can also use explicit with conversion operators.

\n\n

Here's a summary of when explicit is especially useful:

\n\n
    \n
  • Single-argument constructors — the most common case. If a constructor takes one parameter, think twice before making it implicit.
  • \n
  • Constructors with multiple arguments where only the first has a default value — for example, Fraction(int num, int den = 1).
  • \n
  • Conversion operators — starting from C++11, you can mark them as explicit to prevent accidental conversions.
  • \n
\n\n

Remember: explicit is your friend. Use it, and your code will become safer, clearer, and more predictable.

Blogs

Book Recommendations