Question

What the explicit Keyword Means in C++

cppconstructorexplicitc++-faqexplicit-constructor

Question

In C++, what does the explicit keyword mean, and how does it affect constructors or conversion behavior?

Short Answer

By the end of this page, you will understand what explicit does in C++, why it is used to prevent unwanted implicit conversions, where it can be applied, and how to use it correctly with constructors and conversion operators.

Concept

In C++, the explicit keyword tells the compiler not to use a constructor or conversion operator for implicit conversions.

This matters because C++ can automatically convert one type into another in some situations. That can be convenient, but it can also create confusing bugs when a value is converted in a way you did not intend.

A very common case is a constructor that takes one parameter. Without explicit, that constructor can often be used as an implicit converting constructor.

For example:

class Distance {
public:
    Distance(int meters) {}
};

void printDistance(Distance d) {}

int main() {
    printDistance(5); // allowed: int is implicitly converted to Distance
}

Here, 5 is not a Distance, but C++ silently creates a Distance(5) object.

If that constructor is marked explicit, the compiler will refuse the automatic conversion:

class Distance {
public:
    explicit Distance(int meters) {}
};

void printDistance(Distance d) {}

int main() {
    printDistance(5);           // error
    printDistance(Distance(5)); // OK
}

Now the conversion must be written clearly.

Why this matters

explicit improves code by:

  • preventing accidental conversions
  • making APIs easier to understand
  • reducing surprising behavior
  • making code safer and more readable

Where explicit is used

In modern C++, explicit is mainly used with:

  • constructors
  • conversion operators

Explicit constructor

class StringSize {
public:
    explicit StringSize(int n) : size(n) {}

private:
    int size;
};

Explicit conversion operator

class Flag {
public:
    explicit operator bool() const {
        return true;
    }
};

This means the object cannot automatically turn into bool in every context unless the language specifically allows that usage or you convert it explicitly.

Historical note

Traditionally, explicit was mainly associated with single-argument constructors, because those are the most obvious source of implicit conversions. In modern C++, the idea is broader: use explicit whenever you want to block automatic conversion behavior.

Mental Model

Think of explicit as a manual-only sign on a door.

Without explicit, C++ sees a constructor or conversion path and says:

  • "I can convert this automatically for you."

With explicit, you are telling C++:

  • "Do not do this automatically. Only do it when I clearly ask for it."

So:

  • implicit conversion = automatic gearbox
  • explicit conversion = manual gearbox

If a class can be created from an int, a std::string, or another type, explicit forces the programmer to say exactly when that conversion should happen. That makes the code less magical and easier to trust.

Take Quiz

Syntax and Examples

Basic syntax

Explicit constructor

class MyType {
public:
    explicit MyType(int value) {}
};

Explicit conversion operator

class MyType {
public:
    explicit operator bool() const {
        return true;
    }
};

Example 1: Constructor without explicit

#include <iostream>
using namespace std;

class Box {
public:
    Box(int size) {
        cout << "Box created with size " << size << endl;
    }
};

void openBox(Box b) {}

int main() {
    openBox(10); // int automatically becomes Box(10)
}

What happens

Because the constructor takes one int, the compiler is allowed to convert 10 into a Box object automatically.

Example 2: Constructor with explicit

#include <iostream>
using namespace std;

class Box {
public:
    explicit Box(int size) {
        cout << "Box created with size " << size << endl;
    }
};

void openBox(Box b) {}

int main() {
    // openBox(10); // error
    openBox(Box(10)); // OK
}

Why this is better

The caller must clearly say: "Create a Box from 10." That makes the conversion visible.

Example 3: Explicit conversion operator

#include <iostream>
using namespace std;

class Connection {
public:
    explicit operator bool() const {
        return true;
    }
};

int main() {
    Connection c;

    if (c) {
        cout << "Connection is valid" << endl;
    }

    // bool b = c; // may be disallowed because conversion is explicit
    bool b = static_cast<bool>(c); // OK
}

This is useful for types that can be checked like true/false, but should not freely behave like integers or booleans everywhere.

Step by Step Execution

Traceable example

#include <iostream>
using namespace std;

class Temperature {
public:
    explicit Temperature(int c) : celsius(c) {}

    int get() const {
        return celsius;
    }

private:
    int celsius;
};

void show(Temperature t) {
    cout << t.get() << "C" << endl;
}

int main() {
    Temperature t1(25);
    show(t1);
    show(Temperature(30));
    // show(30); // error
}

Step by step

  1. The class Temperature has a constructor that takes one int.
  2. That constructor is marked explicit.
  3. In main, Temperature t1(25); is valid because the code directly creates a Temperature.
  4. show(t1); is valid because t1 is already a Temperature.
  5. show(Temperature(30)); is valid because the conversion is written explicitly.
  6. show(30); is not allowed because the compiler is not allowed to silently turn 30 into Temperature(30).

Key takeaway

explicit does not stop object creation. It only stops automatic conversion when the compiler tries to do it for you.

Real World Use Cases

1. Wrapper types

If you create a class that wraps a primitive value, such as UserId, Meter, Price, or PortNumber, you usually do not want random integers to become those types automatically.

class UserId {
public:
    explicit UserId(int value) : value(value) {}
private:
    int value;
};

This prevents mistakes like passing a plain int where a meaningful domain type is expected.

2. Safer APIs

Libraries often use explicit to make function calls clearer.

class Timeout {
public:
    explicit Timeout(int ms) : milliseconds(ms) {}
private:
    int milliseconds;
};

Then callers must write Timeout(500) instead of just 500, which makes code easier to read.

3. Boolean-like objects

Some classes represent a valid/invalid state, such as file handles, database connections, or smart resource wrappers.

class FileHandle {
public:
    explicit operator bool() const {
        return true;
    }
};

This lets code use if (handle) while avoiding too much automatic conversion elsewhere.

4. Preventing hidden bugs

If a constructor accepts a string, number, or pointer, unintended implicit conversion can make the wrong overload or function call compile. explicit reduces that risk.

Take Quiz

Real Codebase Usage

In real C++ projects, developers often default to marking single-argument constructors as explicit unless they specifically want implicit conversion.

Common patterns

Guarding domain types

class PortNumber {
public:
    explicit PortNumber(int port) : port(port) {}
private:
    int port;
};

This prevents accidentally passing a plain integer into APIs that expect something more meaningful.

Validation at construction time

#include <stdexcept>

class Age {
public:
    explicit Age(int value) {
        if (value < 0) {
            throw std::invalid_argument("Age cannot be negative");
        }
        age = value;
    }

private:
    int age;
};

Here explicit works well with validation because object creation is intentional and visible.

Error-safe APIs

When constructors represent important state changes, implicit conversion can hide expensive or unsafe operations. explicit makes those operations obvious.

Conversion operators used carefully

Developers may define explicit operator bool() for objects that can be tested in conditions.

class Socket {
public:
    explicit operator bool() const {
        return connected;
    }

private:
    bool connected = true;
};

This allows readable checks like:

Socket s;
if (s) {
    // use socket
}

while still avoiding unrestricted automatic conversion in unrelated expressions.

Practical rule

A good default is:

  • use explicit for single-parameter constructors
  • remove it only when implicit conversion is clearly desirable and safe

Common Mistakes

1. Thinking explicit prevents direct construction

explicit does not stop this:

class A {
public:
    explicit A(int x) {}
};

A a(5); // OK

It only stops implicit conversion.

2. Assuming it only applies to one-argument constructors forever

Beginners often hear that explicit is for one-argument constructors. That is the classic case, but modern C++ also uses it with conversion operators.

class A {
public:
    explicit operator bool() const {
        return true;
    }
};

3. Forgetting why implicit conversion is dangerous

Broken example:

class Money {
public:
    Money(int amount) : amount(amount) {}
private:
    int amount;
};

void pay(Money m) {}

int main() {
    pay(100); // compiles, but may be less clear than intended
}

Safer version:

class Money {
public:
    explicit Money(int amount) : amount(amount) {}
private:
    int amount;
};

void pay(Money m) {}

int main() {
    pay(Money(100));
}

4. Overusing implicit conversions in APIs

If your class represents a meaningful business concept, allowing silent conversion from primitive types can make code ambiguous and error-prone.

5. Confusing explicit with const

These keywords solve different problems:

  • explicit controls automatic conversion
  • const prevents modification

They are unrelated, even though both are common in constructors and methods.

Comparisons

explicit vs non-explicit

VersionImplicit conversion allowed?ReadabilitySafety
Constructor without explicitYesLower when conversions are hiddenLower
Constructor with explicitNoHigher because intent is visibleHigher

Example comparison

Without explicit

class Size {
public:
    Size(int v) : value(v) {}
private:
    int value;
};

void print(Size s) {}
print(42); // allowed

With explicit

class Size {
public:
    explicit Size(int v) : value(v) {}
private:
    int value;
};

void print(Size s) {}
print(Size(42)); // required

explicit constructor vs explicit conversion operator

FeaturePurposeExample
explicit constructorPrevent automatic creation of an object from another typeexplicit PersonId(int id);
explicit conversion operatorPrevent automatic conversion from your class to another typeexplicit operator bool() const;

When not to use explicit

Sometimes implicit conversion is part of the intended design. For example, a small helper type may intentionally accept automatic conversion if that makes the API natural and safe. But this should be a deliberate decision, not the default.

Take Quiz

Cheat Sheet

Quick reference

Purpose

explicit prevents implicit conversions through constructors or conversion operators.

Common syntax

class A {
public:
    explicit A(int x);
    explicit operator bool() const;
};

What it blocks

class A {
public:
    explicit A(int x) {}
};

void f(A a) {}

f(10);    // error
f(A(10)); // OK

What it allows

A a(10);     // OK
A b{10};     // OK
A c = A(10); // OK

Main use cases

  • single-parameter constructors
  • wrapper/domain types
  • safe boolean conversion
  • clearer APIs

Good default rule

  • Mark single-argument constructors explicit unless you truly want implicit conversion.

Remember

  • explicit does not stop construction
  • explicit stops automatic conversion
  • it improves clarity and safety

FAQ

What does explicit do in C++?

It prevents the compiler from using a constructor or conversion operator for automatic implicit conversions.

Why is explicit used with constructors?

It stops values like int or string from silently becoming objects of your class when that behavior is not intended.

Does explicit only apply to constructors?

No. It is also used with conversion operators, such as explicit operator bool() const.

Can I still create an object if the constructor is explicit?

Yes. You can still create the object directly, for example MyType x(5);. You just cannot rely on automatic conversion.

Should I always mark single-argument constructors as explicit?

That is a good default in most codebases. Only allow implicit conversion when it clearly improves the design and is safe.

What is the difference between implicit and explicit conversion?

Implicit conversion happens automatically. Explicit conversion requires the programmer to write the conversion clearly in code.

Does explicit make code safer?

Yes. It reduces accidental conversions and makes intent clearer, which helps prevent bugs.

Why does if (obj) sometimes still work with explicit operator bool()?

Because C++ allows boolean checks in certain conditional contexts, while still preventing unrestricted automatic conversion in other places.

Take Quiz

Mini Project

Description

Build a small C++ program that models a UserId type. The project demonstrates why explicit is useful when wrapping primitive values such as integers in safer domain-specific types.

Goal

Create a type-safe UserId class that prevents accidental implicit conversion from int while still allowing clear, intentional object creation.

Requirements

  • Create a UserId class with a constructor that takes an int.
  • Mark the constructor with explicit.
  • Write a function that accepts a UserId parameter.
  • Show valid direct construction and function calls.
  • Include one commented line that would fail because implicit conversion is blocked.
Take Quiz

Keep learning

Related questions

View more