- Learn C++ - https://www.learncpp.com -

13.14 — Converting constructors, explicit, and delete

By default, C++ will treat any constructor as an implicit conversion operator. Consider the following case:

Although function printFraction() is expecting a Fraction, we’ve given it the integer literal 6 instead. Because Fraction has a constructor willing to take a single integer, the compiler will implicitly convert the literal 6 into a Fraction object. It does this by initializing printFraction() parameter f using the Fraction(int, int) constructor.

Consequently, the above program prints:


This implicit conversion works for all kinds of initialization (direct, uniform, and copy).

Constructors eligible to be used for implicit conversions are called converting constructors (or conversion constructors). Prior to C++11, only constructors taking one parameter could be converting constructors. However, with the new uniform initialization syntax in C++11, this restriction was lifted, and constructors taking multiple parameters can now be converting constructors.

The explicit keyword

While doing implicit conversions makes sense in the Fraction case, in other cases, this may be undesirable, or lead to unexpected behaviors:

In the above example, the user is trying to initialize a string with a char. Because chars are part of the integer family, the compiler will use the converting constructor MyString(int) constructor to implicitly convert the char to a MyString. The program will then print this MyString, to unexpected results. Similarly, a call to printString(‘x’) causes an implicit conversion that results in the same issue.

One way to address this issue is to make constructors (and conversion functions) explicit via the explicit keyword, which is placed in front of the function’s name. Constructors and conversion functions made explicit will not be used for implicit conversions or copy initialization:

The above program will not compile, since MyString(int) was made explicit, and an appropriate converting constructor could not be found to implicitly convert ‘x’ to a MyString.

However, note that making a constructor explicit only prevents implicit conversions. Explicit conversions (via casting) are still allowed:

Direct or uniform initialization will also still convert parameters to match (uniform initialization will not do narrowing conversions, but it will happily do other types of conversions).

Rule: Consider making your constructors and user-defined conversion member functions explicit to prevent implicit conversion errors

The delete keyword

In our MyString case, we really want to completely disallow ‘x’ from being converted to a MyString (whether implicit or explicit, since the results aren’t going to be intuitive). One way to partially do this is to add a MyString(char) constructor, and make it private:

However, this constructor can still be used from inside the class (private access only prevents non-members from calling this function).

A better way to resolve the issue is to use the “delete” keyword (introduced in C++11) to delete the function:

When a function has been deleted, any use of that function is considered a compile error.

Note that the copy constructor and overloaded operators may also be deleted in order to prevent those functions from being used.

13.15 -- Overloading the assignment operator [1]
Index [2]
13.13 -- Copy initialization [3]