Implicit Conversion
An implicit conversion is an automatic conversion from one type to another performed by the compiler without an explicit cast.
A Tempting Shortcut
Suppose a class named Vector has a constructor that accepts a single int. When you write Vector v1(7);, the program builds a Vector that holds 7 elements. Seeing this, it is natural to assume that the number 7 is simply turned into a Vector wherever a Vector is expected. Under that assumption, the statement Vector v2 = 7; should work just as well. This section examines that belief, shows why it is wrong for this class, and gives you a method for finding the exact place where a conversion is rejected.
What do you think happens?
Both statements start from the integer 7. Does Vector v2 = 7; compile, given that Vector v1(7); compiles?
Reveal answer
No, it is a compile error
Vector v1(7); is valid, but Vector v2 = 7; is a compile error because there is no implicit conversion from int to Vector. Being able to construct an object directly does not mean the compiler will convert values of that type implicitly.
Tracing the Two Declarations
Read the two declarations side by side. The first one asks the compiler to construct a Vector directly, using 7 as the constructor argument. The second one asks the compiler to make a Vector from the value 7 and store it in v2, with no constructor call written in an explicit form. The compiler accepts the first and rejects the second. Creating a Vector from the number 7 is a different operation from letting the compiler silently replace a 7 with a Vector.
- The first line names the construction explicitly and is accepted.
- The second line requires the compiler to bridge an int to a Vector on its own, and it cannot do so for this class.
The sequence above describes what a conversion would look like if it were allowed. In the Vector case from the source, the compiler does not take these steps for the copy-style declaration, so the statement is rejected. The key point is that a constructor existing for int is not enough by itself. The conversion path must also be permitted.
Direct Construction Versus Copy-Style Initialization
Direct construction and copy-style initialization can look similar, but they ask for different things. Direct construction, as in Vector v1(7);, names the constructor call through the parentheses and passes 7 as its argument. Copy-style initialization, as in Vector v2 = 7;, uses the equals sign and expects the value on the right to already be of the target type or to be converted to it. When the right side is an int and the target is a Vector, the second form requires an implicit conversion. Direct construction does not require one.
Single-Argument Constructors as Conversions
A constructor that takes exactly one parameter does more than build an object when you call it directly. It can also let the compiler create that object automatically when a value of the parameter's type appears where the new type is expected. In that case the constructor is serving as a conversion from its parameter type to its class type. The Vector constructor that accepts an int is an example: it defines a conversion from int to Vector, and whether that conversion is actually used depends on how the constructor is declared and on the context.
Implicit conversion can make code convenient, but it can also hide an unintended interpretation of a value. A conversion from double to a complex class can be useful, because it lets a plain numeric value serve as a complex number. A conversion from int to Vector is misleading, because the integer is being read as a count of elements, not as the same kind of thing a Vector is. The usefulness of a conversion depends on what the argument means for that class.
How the explicit Keyword Blocks Conversion
Marking a single-argument constructor with the explicit keyword blocks implicit use of that constructor without removing direct construction. The compiler will no longer use the constructor to bridge a mismatch between an int and a Vector in a copy-style declaration. But the direct form still works, because it names the construction explicitly and passes the constructor's argument. The source puts it this way: if the constructor is explicit, the compiler is not allowed to bridge the mismatch implicitly, while the direct form succeeds.
- The explicit keyword sits in front of the one-argument constructor declaration.
- Removing the implicit path does not remove the direct path.
Deciding Whether a Constructor Should Be explicit
Whether a single-argument constructor should be explicit depends on the intended use of the class. The guidance in the source is to use explicit unless there is a good reason to allow automatic conversion. The decision turns on whether the conversion's meaning is clear to the people who use the class. If the argument naturally represents a value of the class, an implicit conversion may be reasonable. If the argument means something different, such as a count of elements in a Vector, an implicit conversion can mislead readers and should be blocked.
Locating the Failing Line
When a program does not behave as expected, the most useful question is where the actual result first departs from the expected one. For the two Vector declarations, the expected result of the second statement is a Vector holding 7 elements, because the first statement shows that a Vector can hold 7 elements. The actual result is a compile error at the assignment. The divergence occurs at the assignment, not at the constructor call. Narrowing the problem to one line is the fastest way to find the cause.
In the failing line, the expression supplies an int, but the destination is a Vector. That mismatch is the place to look. The token 7 is where the compiler would need a conversion it is not allowed to perform, so the error is reported at that assignment.
Mistakes Beginners Make with Conversions
Common mistake Assuming that any value a constructor accepts can be assigned to the class directly
What it looks likeVector v2 = 7; after writing Vector v1(7);Why it failsDirect construction and implicit conversion are separate operations. Vector v1(7) names a constructor call, but the assignment form needs the compiler to make the conversion on its own, and this class does not allow that.
Do this insteadWrite the construction directly, as in Vector v2(7);, or change the design if an implicit conversion is really intended.
Common mistake Treating Vector v2 = 7 as if it stores the number 7 in the vector
What it looks likeReading the line as setting v2 to hold the value 7
Why it failsThe integer is being interpreted as a count of elements. That interpretation is hidden by the assignment syntax, which is why the source calls it misleading.
Do this insteadUse the direct form so the meaning of the argument is visible in the code.
Common mistake Removing explicit and expecting direct construction to break
What it looks likeThinking explicit stops Vector v1(7); from compiling
Why it failsThe explicit keyword blocks implicit use of the constructor without removing direct construction.
Do this insteadKeep the direct form in code that uses explicit constructors.
Common mistake Marking a constructor implicit by default without asking whether the argument's meaning matches the class
Practice Predicting Declarations
A class Meters has one constructor, Meters(double), that is not explicit. For each declaration, predict whether it compiles: (a) Meters m1(3.5); (b) Meters m2 = 3.5; (c) Meters m3 = 2; Then explain which of these depend on an implicit conversion from a value to Meters, and locate the exact line where a conversion would be needed.
Hints
- Start by asking whether each declaration is direct construction or copy-style initialization.
- A value of type int can be converted to double as part of the argument, but the question is whether a conversion from the initializer to Meters is permitted.
- Compare your answer with the Vector example: a constructor existing for a type does not by itself settle whether the implicit path is allowed.
Explain, in one or two sentences, whether the Meters(double) constructor in the previous question should be explicit, using the test of whether the argument's meaning is clear to users of the class.
Hints
- Think about whether a plain number reads naturally as a length in meters.
Key Takeaways
- An implicit conversion is an automatic conversion from one type to another performed by the compiler without an explicit cast.
- A single-argument constructor can provide a conversion from its parameter type to its class type, but being able to construct an object directly does not mean the compiler will convert values implicitly.
- Vector v1(7); is valid, while Vector v2 = 7; is a compile error because there is no implicit conversion from int to Vector.
- The explicit keyword blocks implicit use of a constructor without removing direct construction, and the default guidance for single-argument constructors is to use explicit unless there is a good reason to allow automatic conversion.
- When a declaration fails, find the exact line where the expected and actual results diverge, and ask where one type is required while another is supplied.